Ajax don't transmit data - ajax

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.

Related

Django: How to send csrf_token with Ajax

I have my Ajax in a jQuery function:
btnApplyConfig.js:
$(".btnApplyConfig").click(function(){
var token = $("input[name=csrfmiddlewaretoken]").val();
// Some other vars I'm sending properly
console.log('token: '+token); //printing correctly
$("#"+frm).submit(function(e){
e.preventDefault();
console.log('Post method via ajax');
$.ajax({
url: '/ajax/validate_config',
type: 'POST',
data: {
'token': token,
//and other stuff I'm sending properly
},
dataType: 'json',
});
});
});
my Django view:
def validate_config(request):
token = request.GET.get('token', None)
#some other vars I've sent ok with ajax
data = {
#some vars
'token': token,
}
if request.method == 'POST':
item = MyClass.objects.filter(my_keyword=my_filter_values).update(my_ajax_values)
return JsonResponse(data)
All the data is being processed properly, the only problem for me is that I'm getting the following error:
Forbidden (CSRF token missing or incorrect.): /ajax/validate_config/
I've put some prints in view in order to check if vars are being sent properly, and yes they are.
How could I handle it?
I checked some tutorials but I couldn't find a solution so far.
A very simpler way
let cookie = document.cookie
let csrfToken = cookie.substring(cookie.indexOf('=') + 1)
$.ajax({
url: 'url/path',
type: 'POST',
headers: {
'X-CSRFToken': csrfToken
}
})
You can use this. You don't have to put anything in your view for it. It will automatically find it.
$.ajax({
url: ,
type: "POST",
data: {
'csrfmiddlewaretoken': $("input[name=csrfmiddlewaretoken]").val()
// plus other data
},
dataType: 'json',
success: ,
});
You probably also want to add if request.is_ajax() to your view.
This was the solution that worked for me in this case:
Added this code before the Ajax code:
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');
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);
}
}
});

Update method from the ajax call on django rest api?

There is a update view api made to update the content of employee. I can update from the django rest framework view.
I'm using jquery ajax to update but its not working.
$(document).ready(function(){
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');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(".update-employee").submit(function(event){
event.preventDefault()
var this_ = $(this)
var form = this_.serializeArray()
$.each(form, function(key, value){
})
var formData = this_.serialize()
console.log(formData);
var temp =
{
"name": form[4].value,
"email": form[1].value,
"address": form[2].value,
"phone_number": form[3].value,
"username": {{ user_id }},
"school": {{ school_id}},
"language_id": {{ language_id }}
}
$.ajax({
url: "/api/student/{{ id }}",
data: JSON.stringify(temp),
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
method: "PUT",
contentType: "application/json; charset=utf-8",
dataType: 'json',
success: function(data){
console.log(data)
},
error: function(data){
console.log("error")
console.log(data.statusText)
console.log(data.status)
}
})
});
});
The temp variable uses the values to update which is sent through context data from views.
what is the problem here, its showing error in console.

Handling Django Model Form Error in Ajax Submit

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'.

Passing AJAX request in MVC3 environment

I was using MVC3 with AJAX. I was using AJAX within another AJAX. For the first AJAX request, it properly sends to the controller with data. But after returning from the AJAX request, I again posting the same data to another action. But second time the data comes null when coming to the controller. Please help me to fix this issue.
Code
$(document).ready(function () {
$('.deleteitems').live('click', function (e) {
var items = [];
$('.checkall').each(function () {
if ($(this).is(':checked'))
items.push($(this).attr("Id"));
});
var json = JSON.stringify(items);
var perm = $("#Permission").val();
if (items.length != 0) {
if (perm == "True") {
$.ajax({
url: '/ItemControl/ItemControl/Catalogue_Check',
type: 'POST',
dataType: 'json',
data: json,
contentType: 'application/json; charset=utf-8',
success: function (data) {
if (data == "S") {
DelBibsAlso();
}
else {
DelItemsonly();
}
}
});
}
else {
$("#divMes").removeClass("Success");
$("#divMes").addClass("Error");
showError("Sorry you dont have Permission!");
}
}
else {
alert("Select any Items to delete");
e.preventDefault();
}
});
});
function DelItemsonly() {
var items2 = [];
$('.checkall').each(function () {
if ($(this).is(':checked'))
items2.push($(this).attr("Id"));
});
var itemjson = JSON.stringify(items2);
var val = confirm("Are you sure you want to delete these records?");
if (val) {
$.ajax({
url: '/ItemControl/ItemControl/DeleteItems',
type: 'POST',
dataType: 'json',
data: { "id": itemjson, "DelBib": 0 },
contentType: 'application/json; charset=utf-8',
success: function (data) {
e.preventDefault();
$(".t-grid .t-refresh").trigger('click');
$("#divMes").removeClass("Error");
$("#divMes").addClass("Success");
showError("Data Successfully Deleted");
}
});
}
else {
e.preventDefault();
}
}
function DelBibsAlso() {
var items1 = [];
$('.checkall').each(function () {
if ($(this).is(':checked'))
items1.push($(this).attr("Id"));
});
var bibjson = JSON.stringify(items1);
var value = confirm("Do you also want to delete the catalogue record?");
var cond = 0;
if (value) {
var cond = 1;
}
else {
cond = 0;
}
var val = confirm("Are you sure you want to delete these records?");
if (val) {
$.ajax({
url: '/ItemControl/ItemControl/DeleteItems',
type: 'POST',
dataType: 'json',
data: { "id": bibjson, "DelBib": cond },
contentType: 'application/json; charset=utf-8',
success: function (data) {
e.preventDefault();
$(".t-grid .t-refresh").trigger('click');
$("#divMes").removeClass("Error");
$("#divMes").addClass("Success");
showError("Data Successfully Deleted");
}
});
}
else {
e.preventDefault();
}
}
Controller Code
public ActionResult Catalogue_Check(string[] id)
{
DeleteItem weed = new DeleteItem();
int[] ints = id.Select(x => int.Parse(x)).ToArray();
var Matched_BibID = (from asd in Db.Items
where ints.Contains(asd.Id)
select asd.BibId).ToList();
foreach (var idd in ints)
{
var bibid = (from bib in Db.Items where bib.Id == idd select bib.BibId).Single();
var checkbib = (from bibchk in Db.Items where bibchk.BibId == bibid && !ints.Contains(bibchk.Id) select bibchk.Id).Count();
if (checkbib == 0)
{
return Json("S", JsonRequestBehavior.AllowGet);
}
}
return Json("N", JsonRequestBehavior.AllowGet);
}
public JsonResult DeleteItems(string[] id, int? DelBib)
{
//var newid = id.Split(',');
DeleteItem weed = new DeleteItem();
int[] ints = id.Select(x => int.Parse(x)).ToArray();
foreach (var a in id)
{
int sel = Convert.ToInt32(a);
Item item = Db.Items.Single(i => i.Id == sel);
int Sess = Convert.ToInt16(Session["AccId"]);
string AdminName = User.Identity.Name;
bool Exist = Db.RouteOuts.Any(itm => itm.ItemId == item.Id);
if (!Exist)
{
weed.DeleteIt(item, Sess, AdminName);
var bibid = (from bib in Db.Items where bib.Id == item.Id select bib.BibId).Single();
var checkbib = (from bibchk in Db.Items where bibchk.BibId == bibid && !ints.Contains(bibchk.Id) select bibchk.Id).Count();
if (checkbib == 0)
{
Db.ExecuteStoreCommand("update Bibs set Status= 'D' where Id={0}", item.BibId);
Db.SaveChanges();
}
}
}
return Json("S", JsonRequestBehavior.AllowGet);
}
function Test() {
var items1 = [];
$('.checkall').each(function () {
if ($(this).is(':checked'))
items1.push($(this).attr("Id"));
});
//var bibjson = JSON.stringify(items1); **** Loose this line ****
var value = confirm("Do you also want to delete the catalogue record?");
var cond = 0;
if (value) {
var cond = 1;
}
else {
cond = 0;
}
var val = confirm("Are you sure you want to delete these records?");
if (val) {
$.ajax({
url: '/ItemControl/ItemControl/DeleteItems',
type: 'POST',
dataType: 'json',
data: JSON.stringify({ "id": items1, "DelBib": cond }), // **** Items are stringified before posting ****
contentType: 'application/json; charset=utf-8',
success: function (data) {
e.preventDefault();
$(".t-grid .t-refresh").trigger('click');
$("#divMes").removeClass("Error");
$("#divMes").addClass("Success");
showError("Data Successfully Deleted");
}
});enter code here
}
else {
e.preventDefault();
}

X-editable inline editing in Django - how to get CSRF protection?

I am trying to get X-Editable inline editing of a model in Django. I am simply trying to change attributes of a model instance (in this case, the name of a Dataset object).
I am not sure how to write the view so that it correctly captures the information from the ajax request:
POST /datasets/9/update_name/
{
pk: 3 //primary key (record id)
value: 'The Updated Name' //new value
}
Then save the new name to the Dataset object.
urls.py
# ex: /datasets/3/update_name
url(r'^(?P<pk>\d+)/update_name/$', update_name ,
name='update_name'),
detail.html
<h1 class="page-title center">
{{ dataset.name }}
</h1>
<script>
$('#datasetName').editable({
type: 'text',
pk: {{ dataset.pk }},
url: '{% url 'datasets:update_name' dataset.pk %}',
title: 'Edit dataset name'
params: { csrf: '{% csrf_token %}'} # // This isn't working
});
</script>
views.py
def update_name(request, dataset_id):
# ... Update Dataset object ...
json = simplejson.dumps(request.POST)
return HttpResponse(json, mimetype='application/json')
EDIT:
I believe the problem is that there is no CSRF protection. How can I add this in the X-editable form?
** EDIT 2:
I have also tried this, as per the docs:
<h1 class="page-title center">
{{ dataset.name }}
</h1>
<script>
// using 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');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
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;
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
$('#datasetName').editable({
type: 'text',
pk: {{ dataset.pk }},
url: '{% url 'datasets:update_name' dataset.pk %}',
title: 'Edit dataset name',
});
</script>
Wow, I spent so much time on this problem!
The shortlist version would be:
{{ project.name }}
And then, call
$('#projectname{{project.id}}').editable();
The correct name for csrf form field is csrfmiddlewaretoken.
I faced this in my PHP Project and I solved it by using the ajaxOptions option. Picked up the CSRF Token from the meta tag and added it to the request header.
ajaxOptions: {
dataType: 'json',
beforeSend: function(xhr){
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]')
.attr('content'));
}
}
I think the correct one especially if you are working with rails to add
ajaxOptions: {
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
},
inside editable function to be
$('#projectname').editable({
showbuttons: 'bottom',
ajaxOptions: {
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
},
type: 'textarea',
url: '/url/url'
});

Resources