I send data from html fields via AJAX
var dataToSend = { some1 : $('.name1').html().replace(/[\n\r]/g, '').trim(),
some2 : $('.name2').html().replace(/[\n\r]/g, '').trim(),
some3 : $('.name3').html().replace(/[\n\r]/g, '').trim(),
some4 : $('.name4').html().replace(/[\n\r]/g, '').trim() }
if (dataToSend) {
$.ajax({
url: 'do/smth',
data: dataToSend,
async: false,
type: 'POST',
success: function() {
alert('draft is saved')
}
});
}
Then i receive POST request which does contain data but my model saves only when all arguments are existing, so for example if i get only {some1:"value1",some2:"value2"} my django view WONT save it.
The question is: how can i possibly save data into db, if my fields are empty, as you can see i have blank=True in my model, but it does not help
model
class Draft(models.Model):
name = models.CharField(_('company name'), max_length=100, blank=True)
slug = models.SlugField(max_length=255, blank=True)
pitch = models.CharField(_('pitch'), max_length=140, blank=True)
url = models.CharField(_('url'), max_length=255, null=True, blank=True)
thesis = models.TextField(_('thesis'), blank=True)
def __unicode__(self):
return self.name
views
def save_from_ajax_post(request):
data = dict(request.POST.items())
draft = Draft.objects.create(data)
draft.save()
return HttpResponse(json.dumps({'status': 1}), content_type="application/json")
Related
I’m trying to build a web app using Django and I want to upload a file (a pdf or word document) using ajax (the ajax module in jquery).
I’m building my API using the django-rest-framework.
I’ve pretty much tried to do what every site says but can’t seem to get around it.
Has anyone done this?
My views:
def contract_post(request):
contract = Contract()
if request.method == 'POST':
serializer = ContractSerializer(contract, data=request.data)
data = {}
if serializer.is_valid():
serializer.create(validated_data=request.data)
handle_uploaded_file(request.FILES['atasament'])
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def handle_uploaded_file(f):
with open(f.name, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
My serializer (it's a nested serializer):
class ContractSerializer(serializers.ModelSerializer):
client = ClientSerializer(read_only=False)
termen = serializers.DateField(format='%Y-%m-%d', default=datetime.date.today)
atasament = serializers.FileField(max_length=None, allow_empty_file=True)
class Meta:
model = Contract
fields = (
'pk',
'tip',
'nr_data',
'obiectul',
'termen',
'atasament',
'client',
)
def create(self, validated_data):
client = validated_data.pop('client')
client_instance, created = Client.objects.get_or_create(**client)
contract_instance = Contract.objects.create(**validated_data, client=client_instance)
return client_instance
My model:
class Contract(models.Model):
TIPURI = (
('P', 'Proiectare'),
('E', 'Executie'),
('D', 'Documentatie'),
)
tip = models.CharField(max_length=300, choices=TIPURI)
nr_data = models.CharField(max_length=50)
obiectul = models.TextField()
termen = models.DateField(default=datetime.date.today)
atasament = models.FileField(upload_to='main/documents/', blank=True, null=True)
client = models.ForeignKey(Client, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.nr_data
class Meta:
verbose_name_plural = "Contracte"
My JS:
$('#form_add').submit(function (event) {
event.preventDefault();
let input_atasament = document.getElementById('input_atasament');
let client_pk = $("#input_clienti").val();
let nr_data = "test";
let tip = $("#input_tip").val();
let obiectul = $("#input_obiectul").val();
let termen = $("#input_termen").val();
const url = \/api/contract-post/`;let client_url = `/api/client-get/${client_pk}`;let client = $.ajax({url: client_url,async: false,dataType: 'json'}).responseJSON;`
let data = new FormData();
data.append('nr_data', "test");
data.append('tip', tip);
data.append('obiectul', obiectul);
data.append('termen', termen);
data.append('atasament', input_atasament.files[0]);
data.append('client', JSON.stringify(client));
var action = function(d) {
console.log(d);
};
$.ajax({
url: url,
headers: {
'X-CSRF-TOKEN': csrftoken,
'Content-Type': 'multipart/form-data',
},
data: data,
type: "POST",
contentType: false,
processData: false,
success: action,
error: action
});
});
And what error I get now:
"Multipart form parse error - Invalid boundary in multipart: None"
Im using angular/typescript where I upload a form of data to my Django REST API. With the data all is correct, because I can log my whole form and I get back all my data. But when it comes to upload the data I get this error:
{src: ["No file was submitted."], tag: ["This field is required."]}
so somehow it does not recognize my data because Im actually submitting data.
frontend code
upload.service
const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'multipart/form-data'})
};
...
uploadPost(src: File, tag: string) {
return this.http.post<any>(`{this.url}/posts/`, {src, tag}, httpOptions);
}
post.page
ngOnInit() {
this.storage.get('image_data').then((imageFile) => {
console.log(imageFile)
this.categoryForm.patchValue({
'image': this.storage.get('image_data')
});
});
this.categoryForm = new FormGroup({
'category': new FormControl('', Validators.compose([
Validators.maxLength(25),
Validators.minLength(1),
Validators.required
])),
'image': new FormControl(null),
});
apiSubmit() {
console.log('logged')
console.log(this.f.image);
this.submitted = true;
if (this.categoryForm.invalid) {
return;
}
this.isLoading = true;
this.loadingEl.present();
this.uploadService.uploadPost(
this.f.image,
this.f.category
)
.pipe(tap(x => this.loadingEl.dismiss())
)
.subscribe(
data => {
this.router.navigate(['one']);
},
error => {
this.error = error;
}
);
}
Django:
models.py
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='posts', on_delete=models.CASCADE)
src = models.ImageField(blank=False, null=False, editable=False, upload_to=utils.get_file_path,)
date_posted = models.DateTimeField(auto_now_add=True, editable=False)
last_modified = models.DateTimeField(auto_now=True)
when = models.FloatField(blank=True, null=True)
lock = models.BooleanField(default=False)
des = models.CharField(
max_length=100,
validators=[
RegexValidator(
regex='^[-_a-zA-Z0-9\.]+$',
message='only 1 to 20 characters and only letters, numbers, point, minus and underscore are allowed',
),
])
view.py
#swagger_auto_schema(request_body=doc_serializer.CreatePostDummy, responses={201: PostSerializer})
def create(self, request, *args, **kwargs):
"""permission required: authenticated. Note: the schema is not json it's multipart"""
return super().create(request, *args, **kwargs)
doc_serializers.py
class CreatePostDummy(serializers.HyperlinkedModelSerializer):
`enter code here`user = serializers.HyperlinkedRelatedField(required=False, read_only=True, view_name='user-detail')
src = serializers.CharField(required=True, help_text='Not Char but image upload field')
hey i tried this code but still have an error that is Not Null constraint failed i know this is because of my cheque_no that is unique type but how could i remove this error i did not remove my cheque_no is unique because its required.now am getting this problem i want to save these entries in my model.
views.py
#csrf_exempt
def jsdata(request):
table_data = json.loads(request.POST.get('MyData'))
# print(table_data)
r_data = {
'success': True,
}
for data in table_data:
# Since you are just creating objects you don't need to save created object in a variable.
Mvouchar.objects.create(bill_no = data['BillNo'], bill_details=data['BillDetails'],am=data['Amount'])
# r_data['success'] = False
# IMO Views responding to ajax requests should send JsonResponse
if r_data['success']:
r_data['msg'] = 'Data Saved'
else:
r_data['msg'] = 'Not all Data Saved'
return JsonResponse(r_data)
models.py
class Mvouchar(models.Model):
related = models.ForeignKey(Signs, on_delete=models.CASCADE, null=True, blank=True)
bill_no = models.CharField(max_length=8000, null=True, blank=True)
bill_details = models.CharField(max_length=10000, null=True, blank=True)
am = models.CharField(max_length=30000, null=True, blank=True)
cheque_no = models.PositiveIntegerField(validators=[MaxValueValidator(6)], unique=True, help_text='integers only')
def __str__(self):
if self.related:
return self.related.relation.username.title()
else:
return 'no related!'
class Meta:
verbose_name_plural = "Single Cheque Multiple Vouchar Of Users"
javascript
$("#btnjson").click(function () {
var array1 = [];
$("tbody tr").each(function () {
var firstTableData = {};
firstTableData.BillNo = $(this).find('td').eq(0).text();
firstTableData.BillDetails = $(this).find('td').eq(1).text();
firstTableData.Amount = $(this).find('td').eq(2).text();
array1.push(firstTableData);
//}
});
alert(JSON.stringify(array1));
$.ajax({
type: "POST",
url: "/jsondata/",
dataType: 'json',
data: {MyData: JSON.stringify(array1)},
success: function(msg){
alert(msg);
}
});
return false;
} );
});
from django.core.validators import RegexValidator
CHEQUE_REGEX = RegexValidator(
regex=r'^\d{6}$',
message="Cheque Number must be exactly 6 digits"
)
class Mvouchar(models.Model):
...
cheque_no = models.CharField(validators=[CHEQUE_REGEX, ], unique=True, max_length=6, help_text='integers only')
...
If you read the second traceback (The first traceback is from a different view views.mvoucha, and you didn't include that code in the question), you'll find that the problem is this line in your view function.
table_data = json.loads(request.POST.get('MyData'))
What's happening is that request.POST.get('MyData') returns None, which can't be represented as json. That's why the json encoder raises a TypeError.
The request.POST dictionary is used with form data. When you want to parse a json payload, you have to use request.body instead. For example like this:
table_data = json.loads(request.body).get('MyData')
https://docs.djangoproject.com/en/2.1/ref/request-response/#django.http.HttpRequest.POST
I'm working on my first Django project (IDE: PyCharm, OS: Win10). There is a problem with .js. I renamed variable called 'nmb' to 'quantity' in the script. This variable was created for counting products in user's cart. Then I've got an error that ItemInCart model gets an 'undefined' quantity instead of some countable value. It happens because only on 8000 port jQuery still seeks for 'nmb' not for data attr name 'quantity'. Running my app on any other port, like 8023 everything works well.
JS
$ (document).ready(function () {
var form = $('#form_buy_item');
console.log(form);
form.on('submit', function (e) {
e.preventDefault();
var quantity = $('#quantity').val();
console.log(quantity);
var csrf_token;
var submit_btn = $('#submit_btn');
var item_id = submit_btn.data('item_id');
var item_name = submit_btn.data('item_name');
var item_price = submit_btn.data('item_price');
console.log(item_name, item_id);
var data = {};
data.item_id = item_id;
data.item_name = item_name;
data.quantity = quantity;
csrf_token = $('#form_buy_item [name = "csrfmiddlewaretoken"]').val();
data["csrfmiddlewaretoken"] = csrf_token;
// use action attribute for multi-language support
var url = form.attr("action");
console.log(data);
$.ajax({
url: url,
type: 'POST',
data: data,
cache: true,
success: [ function (data) {
console.log("OK");
console.log(data.items_total_count);
if (data.items_total_count){
$('#cart_total_quantity').text('data.items_total_count')
}
} ],
error: function() {
console.log("error")
}
});
$('.cart-items ul').append('<li>'+item_name +', ' + quantity + ' item(s), ' + item_price + '$ per item '+
'<a class="delete-item" href=""> x <a>' + '</li>')
});
function displayCartItems(){
$('.cart-items').toggleClass('hidden');
}
$('.cart-container').on('click, hover', function (e) {
e.preventDefault();
displayCartItems();
});
$('.cart-container').mouseover('click, hover', function (e) {
e.preventDefault();
displayCartItems();
});
$('.cart-container').mouseout('click, hover', function (e) {
e.preventDefault();
displayCartItems();
});
$(document).click('click', 'delete-item', function(e) {
e.preventDefault();
$(this).closest('li').removeAttr()
});
});
Model
class ItemInCart(models.Model):
session_key = models.CharField(max_length=128, null=True, blank=True, default=None)
order = models.ForeignKey(Order, on_delete=models.SET_DEFAULT, blank=True, null=True, default=None)
item = models.ForeignKey(Item, on_delete=models.SET_DEFAULT, blank=True, null=True, default=None)
quantity = models.IntegerField(default=1)
price_per_item = models.DecimalField(max_digits=10, decimal_places=2, default=0)
total_price = models.DecimalField(max_digits=10, decimal_places=2, default=0)
is_active = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
class Meta:
verbose_name = 'Item in cart'
verbose_name_plural = 'Items in cart'
def save(self, *args, **kwargs):
price_per_item = self.item.price
self.price_per_item = price_per_item
self.total_price = int(self.quantity) * self.price_per_item
super(ItemInCart, self).save(*args, **kwargs)
Views
def cart_add(request):
return_dictionary = dict()
session_key = request.session.session_key
print(request.POST)
data = request.POST
item_id = data.get('item_id')
quantity = data.get('quantity')
# is_delete = data.get('is_delete')
new_item = ItemInCart.objects.create(session_key=session_key, item_id=item_id, quantity=quantity)
items_total_count = ItemInCart.objects.filter(session_key=session_key, is_active=True).count()
return_dictionary['items_total_count'] = items_total_count
print(request.POST)
return JsonResponse(return_dictionary)
This is happened on 8000, 8001
8024 is fine
Please clear browser history then run the application.
I am getting NOT NULL constraint error even after passing the data from the form. I am using ajax for posting the data. I checked both the request.POST and network request tab. Both shows the store_contact_number has data in it.
Here is my code
class ListStore(FormView):
form_class = StoreForm
template_name = 'Store/list-store.html'
def form_invalid(self, form):
if self.request.is_ajax():
print('ajax form error', form.errors)
response = {
'error': form.errors
}
return JsonResponse(response, status=400)
else:
return super(ListStore, self).form_invalid(form.errors)
def form_valid(self, form):
success_message = "Thank you for listing your store. We Welcome you."
store, created = Store.objects.get_or_create(merchant=self.request.user)
if self.request.is_ajax():
response = {
'result': success_message
}
return JsonResponse(response)
else:
message.success(self.request, success_message)
return self.render_to_response(self.get_context_data())
class Store(models.Model):
merchant = models.ForeignKey(User, blank=False, null=False)
token = models.CharField(default=token_generator, max_length=20, unique=True, editable=False)
name_of_legal_entity = models.CharField(max_length=250, blank=False, null=False)
pan_number = models.CharField(max_length=20, blank=False, null=False)
registered_office_address = models.CharField(max_length=200)
name_of_store = models.CharField(max_length=100)
email = models.EmailField(blank=False, null=False)
store_contact_number = models.PositiveIntegerField(blank=False, null=False)
$('.list-store-form').on('submit', function(event) {
event.preventDefault(); // preventing from the brwoser default behavior for form submission
var form = $(this);
console.log(form);
$.ajax({
async: true,
url: form.attr('action'),
data: form.serialize(),
type: 'POST',
dataType: 'json',
headers: {
'X-CSRFToken': window.csrf_token
},
success: function(data) {
if (data.form_is_valid) {
alert('Store Listed');
}
// $('.display').html(
// "<div class='ui floating message'> <i class='close icon'></i>" + data.result + '</div>'
// );
},
The error is shown in the store_contact_number as
IntegrityError at /list/store NOT NULL constraint failed:
Store_store.store_contact_number
<QueryDict: {'store_contact_number': ['98489678'], 'email': ['admin#gmail.com'], 'registered_office_address': ['Delhi'], 'csrfmiddlewaretoken': ['kSaPMgNt'], 'name_of_store': ['BigMart'], 'pan_number': ['98713962'], 'name_of_legal_entity': ['BigMart Pvt Ltd']}>
Form
class StoreForm(forms.ModelForm):
class Meta:
model = Store
exclude = ('is_active', 'token', 'merchant',)
You need to add store = form.save() at the start of your form_valid method and get rid of the line store, created = Store.objects.get_or_create(merchant=self.request.user).
EDIT: Actually it's not that simple because the form.save() will also fail due to not having the merchant field specified. You'll need to either need to override either the __init__ or save method of your form so you can pass in the merchant.
Something like:
def save(self, merchant, *args, **kwargs):
commit = kwargs.pop('commit', True)
kwargs['commit'] = False
store = super().save(*args, **kwargs)
store.merchant = merchant
if commit:
store.save()
return store
then call it using:
def form_valid(self, form):
store = form.save(merchant=self.request.user)
success_message = "Thank you for listing your store. We Welcome you."
if self.request.is_ajax():
response = {
'result': success_message
}
return JsonResponse(response)
else:
message.success(self.request, success_message)
return self.render_to_response(self.get_context_data())