Handling Django Model Form Error in Ajax Submit - ajax

I want to sumbit a model form with ajax and using model form validation messages:
class ComplaintForm(forms.ModelForm):
class Meta:
model = Complaint
fields = [
'title','body'
]
def clean_body(self):
form_data = self.cleaned_data
body = self.cleaned_data.get('body', False)
if len(body) < 2:
raise forms.ValidationError(u'Please Add Complaint')
return body
def clean(self):
cd = self.cleaned_data
return cd
In my view:
def forms(request):
form = ComplaintForm()
if request.method == "POST":
if request.is_ajax():
form = ComplaintForm(request.POST)
if form.is_valid():
c = form.save(commit=False)
c.user_ip = get_client_ip(request)
c.user = request.user
c.news = news
c.save()
data = serializers.serialize('json', [c,])
else:
data = json.dumps([v for k,v in form.errors.items()])
return HttpResponseBadRequest(data, mimetype='application/json')
return HttpResponse(data, mimetype='application/json')
else:
form = ComplaintForm()
return render_to_response('main/form.html', {'form': form},
context_instance=RequestContext(request))
But, my problem is how could I send data through HttpResponseBadRequest ?
My js is:
$('.complaintform').submit(function(e){
e.preventDefault();
$.ajax({
type: "POST",
url: "/form/",
dataType: "json",
data: $(this).serialize(),
success: function(data) {
$('p').html('ok');
},
error: function(data) {
//how could i insert model form errors here?
}
});
});

Edited my answer. I misunderstood your question initially.
Try this:
$('.complaintform').submit(function(e){
e.preventDefault();
$.ajax({
type: "POST",
url: "/form/",
dataType: "json",
data: $(this).serialize(),
success: function(data) {
$('p').html('ok');
},
statusCode: {
400: function() {
var items = [];
$.each( data, function( val ) {
items.push( val );
});
$('p').html(items.join(""));
}
}
});
});
If that doesn't work, a dirty workaround would be:
1) in the view:
else:
data = json.dumps([v for k,v in form.errors.items()] + ['failed'])
return HttpResponseBadRequest(data, mimetype='application/json')
2) in javascript:
success: function(data) {
if jQuery.inArray("failed", data) {
data.splice("failed", 1);
var items = [];
$.each( data, function( val ) {
items.push( val );
});
$('p').html(items.join(""));
} else {
$('p').html('ok');
}
},
That will work if, for some strange reason, jquery thinks your HttpResponse is 'success'.

Related

Why my controller not getting data from ajax

I'm new to this, I'm trying to get the data from an ajax query
This Is My Ajax
$('#insertfile').on('click',function() {
console.log('a');
var file = document.getElementById('files').files[0];
var name = document.getElementById('names').value;
if( $('#room-status-no').prop('checked') ) {
console.log("status: 1");
var status = 1;
} else {
var status = 0;
console.log("status: 0");
}
var id = document.getElementById('id').value;
let form = new FormData();
console.log(file);
form.append('file', file);
form.append('name', name);
form.append('status', status);
form.append('id', id);
form.append('_method', 'PATCH');
form.append('action', 'update_file');
console.log(id, name, status);
$.ajax({
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
url: "{{ route('this is my route.update', 'update_file') }}",
type: "PATCH",
cache: false,
processData: false,
contentType : false,
dataType: 'json',
data: form,
beforeSend: function() {
$('body').append('<div id="spinnerLoading"><div class="sk-spinner sk-spinner-double-bounce"><div class="sk-double-bounce1"></div><div class="sk-double-bounce2"></div></div></div>');
},
This is my Controller
public function update(Request $request) {
$action = $request->action;
dd($request->all());
if($action == 'update_text'){
return $this->updatetextControl($request);
} else if($action == 'update_file') {
return $this->updateFileControl($request);
}
I'm trying to pass the form data to my laravel controller using dd($request->all());
I was unable to get any data in my controller, I'm not sure if my URL route is the problem or I cant have multiple update functions others thing in one controller, does anyone know a solution? it will be much appreciated, thanks

How submit captcha to the controller using ajax and form data

I have a form with some fields and file upload, rendering as a partial view using ajax in asp.net MVC. when submitting the form, I want to pass all the data to the controller. But if I use $("form").serialize(), it is not passing the selected file to the controller. So I am using formData() to pass the data to the controller. Till this point, everything works fine.
But after adding captcha using CaptchaMvc, it not reaching the controller. Even if I enter valid captcha, it is invalid in the controller.
This is how I send data to the controller using the ajax and formData
var data = new FormData();
var vidFile = null;
if ($("#FileUpload")[0].files.length > 0)
vidFile = $("#FileUpload")[0].files[0];
data.append("detail", $("#detail").val());
data.append("name", $("#name").val());
data.append("FileUpload", vidFile);
$.ajax({
url: "/home/submitData",
type: "POST",
contentType: false,
processData:false,
data: data,
success: function (response) {
if (response.success == true) {
} else {
}
}
});
Is there any way to pass the captcha as well to the controller?
Why can't you validate using different controller function, as follows:
At the time of submission, validate the captcha first, and depending on the result, call another controller function to submit data or show the error.
var submitData = function(){
var data = new FormData();
var vidFile = null;
if ($("#FileUpload")[0].files.length > 0)
vidFile = $("#FileUpload")[0].files[0];
data.append("detail", $("#detail").val());
data.append("name", $("#name").val());
data.append("FileUpload", vidFile);
$.ajax({
url: "/home/submitData",
type: "POST",
contentType: false,
processData:false,
data: data,
success: function (response) {
if (response.success == true) {
//Success
} else {
//Submission failed
}
}
});
}
var validateCaptcha = function(){
$.ajax({
url: "/home/validateCaptcha",
type: "POST",
data: $("form").serialize(),
success: function (response) {
if (response.success == true) {
submitData();
} else {
alert("Invalid Captcha entry");
}
}
});
}
$("form").submit(function(e){
validateCaptcha();
});

Django Manytomanyfield in Ajax Form

I implemented an Ajax CRUD. My Model has one ManyToMany field(category). If i choose only one item for this field everything will be good, but if choose multi items it shows form invalid error. Please tell me what should I do.
model.py:
class BusienssCategory(models.Model):
title = models.CharField(max_length=20, unique=True)
slug = models.SlugField(unique=True)
description = models.CharField(max_length=45)
def __str__(self):
return self.title
class BusienssProfile(models.Model):
title = models.CharField(max_length=20)
description = models.CharField(max_length=40)
category = select2.fields.ManyToManyField(BusienssCategory)
image = models.ImageField(upload_to=upload_image_path, null=True,
blank=True)
def __str__(self):
return self.title
form.py:
class BusinessForm(forms.ModelForm):
class Meta:
model = BusienssProfile
fields = ('title', 'category', 'shortDescription')
view.py:
def save_business_form(request, form, template_name):
data = dict()
form = BusinessForm(request.POST, request.FILES)
if request.method == 'POST':
if form.is_valid():
form.save()
data['form_is_valid'] = True
businesses = BusienssProfile.objects.all()
data['html_business_list'] = render_to_string('business/business_profile/partial_business_list.html', {
'businesses': businesses
})
else:
data['form_is_valid'] = False
context = {'form': form}
data['html_form'] = render_to_string(template_name, context,
request=request)
return JsonResponse(data)
ajax.js:
var saveForm = function() {
var form = $(this);
var data = new FormData($('form').get(0));
var categories = $("#id_category").val();
var featured = $('#id_featured').prop('checked');
var active = $('#id_active').prop('checked');
data.append("image", $("#id_image")[0].files[0]);
data.append("title",$("#id_title").val());
data.append("category", categories);
data.append("description",$("#id_Description").val());
$.ajax({
url: form.attr("action"),
data: data,
processData: false,
contentType: false,
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
Command: toastr["success"]("The profile has been
deleted.", "Success");
}
else {
Command: toastr["error"]("Something has gone wrong!", "Failure")
}
},
error: function(XMLHttpRequest, textStatus, errorThrown, url) {
alert("Status: " + textStatus);
alert("Error: " + errorThrown);
}
});
return false;
};
I've already tested the form without Ajax and it doesn't show any error. I think something must be wrong in Multiselect return value.
Finally I solved the problem by using both of serializeArray and FormData together. I used Formdata to handle image field and serializeArray to serialize manytomanyField (and other fields). Here is my final js file:
var saveForm = function() {
var form = $(this);
serialData = form.serializeArray();
// We need to use FormData to upload image or file
var data = new FormData($('form').get(0));
data.append("image", $("#id_image")[0].files[0]);
var other_data = form.serializeArray();
$.each(other_data,function(key,input){
data.append(input.name,input.value);
});
$.ajax({
url: form.attr("action"),
data: data,
type: form.attr("method"),
dataType: 'json',
cache: false,
processData: false,
contentType: false,
success: function (data) {
...
}
return false;
};

Ajax don't transmit data

I'm using ajax to pass data to a view for save in database.
In javascript the data look correct but in the view is null.
Read the comments in code for other questions and informations
My javascript:
...
var changed_element=[];
var changed_value=[];
document.getElementById('tabella').addEventListener('change', function(event){
...
changed_element.push(element); //list of list of string
changed_value.push(elem[elem.value].text); //list of string
...
});
document.getElementById('btn-save').addEventListener('click', function() {
console.log('changed_element', changed_element) //print the right value
$.ajax({type: 'POST',
url: '/salva-conoscenze-rapporti/',
data: {
changed_element: changed_element,
changed_value: changed_value //<= comma?
},
success: function(msg) {
console.log(msg) //prints 'It works'
document.getElementById('btn-save').style.display = 'none';
} //<= comma?
});
});
My view:
#staff_member_required
#ensure_csrf_cookie #I need this?
def salva_conoscenze_rapporti(request):
if request.is_ajax():
changed_element = request.POST.get('changed_element', None)
changed_value = request.POST.get('changed_value', None)
msg='it works'
print(changed_element) #prints None instead of array
print(changed_value)
else:
msg="it doesn't work"
return HttpResponse(msg)
My template base.html:
...
<script>
var csrftoken = $.cookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
</script>
...
My template:
{% extends 'base.html' %}
...
Basically print(changed_element) should gives the data instead gives None.
My MIDDLEWARE_CLASSES in settings.py:
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
My variables:
changed_element=[ [ "conoscenza", "Cliente1", "Cliente2" ] ];
changed_value=[ "Generale" ];
console.log(changed_element) gives: Array [ Array[3] ]
To get the cookie you also can use with jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
And then, I'll correcting your script.
// $('.btn-save').click(function() { // to simply with jquery
document.getElementById('btn-save').addEventListener('click', function() {
$.ajax({
type: 'POST',
url: '/salva-conoscenze-rapporti/',
data: {
"changed_element" : changed_element,
"changed_value" : changed_value,
"csrfmiddlewaretoken": csrftoken // from `var csrftoken;`
},
success: function(msg) {
console.log(msg) //prints 'It works'
document.getElementById('btn-save').style.display = 'none';
} //<= comma?
});
});
Or like this one:
$('.btn-save').click(function() {
var form = new FormData();
form.append('changed_element', changed_element);
form.append('changed_value', changed_value);
form.append('csrfmiddlewaretoken', getCookie('csrftoken'));
$.ajax({
type: 'POST',
url: '/salva-conoscenze-rapporti/',
data: form,
processData: false,
contentType: false,
success: function(msg) {
console.log(msg) //prints 'It works'
document.getElementById('btn-save').style.display = 'none';
}
});
});
In your views.py
from django.views.decorators.csrf import csrf_protect
#csrf_protect
#staff_member_required
def salva_conoscenze_rapporti(request):
if request.method == 'POST' and request.is_ajax():
changed_element = request.POST.get('changed_element', None)
changed_value = request.POST.get('changed_value', None)
msg = 'it works'
print(changed_element)
print(changed_value)
else:
msg="it doesn't work"
return HttpResponse(msg)
Hope it can help.

Ajax Form Submit with attachment

I have a Form on my Site thats submitted true ajax. This Form has a field where to attache .pdf files. How when submitting the form though the file is not send with the rest of data.
How can i get this to work?
Here is my ajax code:
$('#submit_btn').click(function () {
$.ajax({
type: 'POST',
url: '/contact.php',
dataType: "json",
data: $('#contactform').serialize(),
success: function (data) {
console.log(data.type);
console.log(data.msg);
var nClass = data.type;
var nTxt = data.msg;
$("#notice").attr('class', 'alert alert-' + nClass).text(nTxt).remove('hidden');
//reset fields if success
if (nClass != 'danger') {
$('#contactform input').val('');
$('#contactform textarea').val('');
}
}
});
return false;
});
On the php side i have phpmailer setup and am handling the file so:
if(!empty($_FILES['file'])) {
$_m->addAttachment($_FILES['file']['tmp_name'],$_FILES['file']['name']);
}
$('#submit_btn').click(function () {
var formData = new FormData($('#contactform'));
$.ajax({
type: 'POST',
url: '/contact.php',
// dataType: "json",
data: formData ,
processData: false,
contentType: false,
success: function (data) {
console.log(data.type);
console.log(data.msg);
var nClass = data.type;
var nTxt = data.msg;
$("#notice").attr('class', 'alert alert-' + nClass).text(nTxt).remove('hidden');
//reset fields if success
if (nClass != 'danger') {
$('#contactform input').val('');
$('#contactform textarea').val('');
}
}
});
return false;
});

Resources