I'm looking to send some JSON POST data to a URL in Django which enforces CSRF protection. My Ajax looks like this:
$.ajax({
type: "POST",
url: '/change_ref/'+hash+"/",
data: {"csrfmiddlewaretoken": "{{ csrf_token }}", "new_ref": newref},
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data){
$('#changeref').modal('hide');
alert('Success!');
},
failure: function(errMsg) {
alert('Failure! ' +errMsg);
}
});
My idea is to then parse the JSON on the backend. However, when I examine the POST data passed to the server, it is empty (as seen by CSRF middleware):
This happens also when I wrap the JSON data with JSON.stringify(). The only way I have POST requests working so far is with application/x-www-form-urlencoded Mimetype, but this is undesirable.
My settings.py is pretty vanilla. Are there any extra steps needed in order to make JSON POSTs in Django, or is there something blatantly wrong with this code?
Thanks
CSRF token should be in HTTP header, so also ContentType
var csrftoken = Cookies.get('csrftoken');
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
xhr.setRequestHeader("content-type", "application/json");
}
}
});
You're not sending form-encoded data, so request.POST is not used. Get it from request.body instead.
Related
There are lots of information regarding this topic, but it is still unclear to me what is the correct approach to send and receive json data in django. Whether to use the raw format or not.
Approach1: NOT using the raw format:
#client
$.ajax({
type: "POST",
url: "api",
contentType: "application/json; charset=utf-8",
data: {
csrfmiddlewaretoken: '{{ csrf_token }}',
x: $("#x").val(),
},
success: response,
dataType: 'json',
minLength: 0,
});
# server - views.py:
#api_view(['GET', 'POST'])
#authentication_classes((TokenAuthentication, SessionAuthentication))
#permission_classes((IsAuthenticated,))
#staff_member_required
def api(request):
params = request.POST
Approach2: using the raw format:
# client
$.ajax({
type: "POST",
url: "api",
contentType: "application/json; charset=utf-8",
headers: {'X-CSRFToken': '{{ csrf_token }}'},
data: JSON.stringify({
x: $("#x").val(),
}),
success: response,
dataType: 'json',
minLength: 0,
});
# server - views.py:
#api_view(['GET', 'POST'])
#authentication_classes((TokenAuthentication, SessionAuthentication))
#permission_classes((IsAuthenticated,))
#staff_member_required
def api(request):
params = json.loads(request.data)
I think that when using the raw format, you can pass in lists but without the raw format it does not understand lists in your data.
On the other hand, approach2 requires JSON.stringify and json.dumps.
Also, I do not know why approach2 throws and exception that You cannot access body...
What I want to know is:
Does it matter which approach I take?
If so which approach is proper and why?
If raw json if preferable, then why does it complain with the ajax
request below (see error below)?
This question is solved on django ajax docs:
set a custom X-CSRFToken header to the value of the CSRF token. This is often easier, because many JavaScript frameworks provide hooks that allow headers to be set on every request.
Notice than popular solutions like django-rest-framework is using header approach:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
// Send the token to same-origin, relative URLs only.
// Send the token only if the method warrants CSRF protection
// Using the CSRFToken value acquired earlier
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
django docs suggestion approach:
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);
}
}
});
I'm using .asmx web service and web service method can serialize to json string(3506 record) by using JavaScriptSerializer class and i don't get any error from VisualStudio.
On the other hand my phonegap app using this service and i can consume with that. But my last method contents 3506 records and when i call this method from javascript i get
"error during serialization or deserialization using the json
javascriptserializer"
error.
Should i use paging or smth on web service? If yes can anybody tell me how to do that? Like i said i can use this method from browser. i can get this error when i call on javascript.
$.ajax({
type: "POST",
url: "WEB_SERVICE_URL",
data: "{ dummyParameter:dummy }",
contentType: "application/json; charset=utf-8",
dataType: "json",
beforeSend: function() {
app.showLoading();
},
success: function(msg) {
clCard = JSON.parse(msg.d);
alert(clCard.length);
},
complete: function() {
app.hideLoading();
},
error: function(msg) {
app.hideLoading();
alert('Error');
}
});
Please have a look at this. I think helped you.
I have asked a question regarding invalid label on firebug which happens when I try to retrieve data from my restful web service. Most of the answers I received was about setting a callback function. but I can't seem to get the right juice from it. can you show me an exact code on how to do it? or atleast correct the code here:
type: "GET",
cache: false,
contentType: "application/json; charset=utf-8",
dataType: "jsonp",
processdata:true,
jsonp: false, jsonpCallback: "success",
url: 'http://localhost:8732/Service1/data/10',
success : function success(data) {
jsonResponse = eval("(" + data + ")");
alert(jsonResponse)
},
error : function(req,status, ex) {
alert(ex);
}
Thanks,
Wow, you've got a lot of unnecessary stuff there. Try this:
$.ajax({
url: 'http://localhost:8732/Service1/data/10',
dataType: 'jsonp',
error: function(req, status, ex) {
// your code here
},
success: function(data) {
//your code here
// Please note: you don't need to 'eval' the json response.
// The 'data' variable will be loaded with the object that the json string represents.
// By the way, don't use 'eval', ever.
}
});
jQuery will take care of the callback on the url. See here: http://api.jquery.com/jQuery.ajax/
UPDATE
Why jsonp? If you're getting this from localhost, why not just json? As discussed in the comments below, your server currently is not capable of a jsonp response, but it can do json.
I am trying to run this code in my browser's console:
$.ajax({
dataType: 'json',
url: 'http://www.web2pdfconvert.com/engine?curl=http://www.nytimes.com&outputmode=json?callback=?',
success: function (data) {
if(data.resultcode == 1) {
console.log(true);
} else {
console.log(false);
}
},
});
However, I am getting a Cross Domain Request Error. when I try to make a simple JSON request then also same error occurs, because JSON request cannot be made on Cross Domains. however, when you go to this URL:
http://www.web2pdfconvert.com/engine?curl=http://www.nytimes.com&outputmode=json
You'll be able to see the JSON data. However, a key point written in the documentation of this websites API says that:
json - all conversion data are returned as JSON object. Also JSONP cross domain communication supported usign jQuery.
Thanks in advance.
Use jsonp instead:
$.ajax({
dataType: 'jsonp',
url: 'http://www.web2pdfconvert.com/engine?curl=http://www.nytimes.com&outputmode=json',
jsonp: "callback",
success: function (data) {
if(data.resultcode == 1) {
console.log(true);
} else {
console.log(false);
}
},
});
Am am successfully parsing and sending JSON values from my client for my server side controller to receive and decode
$("#test2").click(function() {
$.ajax({
type: "POST",
url: "<?php echo $this->baseUrl() ?>/expensetypes/add",
data: JSON.stringify(wrapFormValues($('#expensetypes'))),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg){
alert( "Data Saved: " + msg );
}
});
});
However in my controller the code $this->getRequest()->getPost() doesn't seem to receive the JSON object that my client is sending though Firebug clearly shows that my JSON object is being parsed and sent.
What am I missing?
try
print_r($this->getRequest->getParams());
and see what that shows you