POSTing json data to Django (ajax)
1. jQuery.ajax() doesn't automatically encode data to JSON
Your client code is responsible for encoding its data into a json string, otherwise jQuery.ajax() will try to send it as a query-string. Even if you set the 'contentType' to "application/json" and provide an object that can be serialized into json, the ajax() function will turn it into a query-string.$.ajax({
type: 'POST',
contentType: "application/json",
data: {"test": 1});
-> data will be sent as "?test=1"
Note: as long as you don't need to send (complex) objects, it may be easier to send query-string formatted data to Django. See this post for more details.
So, your client code will need to turn its data into a json string, before passing it to ajax().
$.ajax({
type: 'POST',
contentType: "application/json",
data: JSON.stringify({"test": 1}));
This also works on objects:
var tmpObject = new Object();
tmpObject.test = 1;
$.ajax({
type: 'POST',
contentType: "application/json",
data: JSON.stringify(tmpObject));
2. Django doesn't automatically handle JSON encoded data
When form-encoded data is received in a POST request, django will automatically populate its HttpRequest.POST dictionary object (and also HttpRequest.REQUEST). This doesn't happen with json data: HttpRequest.POST will remain empty.The POSTed data is available through HttpRequest.body (or by calling request.read()), which contains the raw HTTP request body as a byte string. To turn it into a python object, your view needs to do the following:
// assuming request.body contains json data which is UTF-8 encoded
json_str = request.body.decode(encoding='UTF-8')
// turn the json bytestr into a python obj
json_obj = json.loads(json_str, ensure_ascii = False)
3. Don't forget to send the csrf_token
Since Django isn't able to parse the json data itself, you can not simply pass the csrf_token as part of your data. If you don't provide the csrf_token in some other way, the CsrfViewMiddleware will raise an exception before your view code is being executed.The easiest way to avoid this, is by setting a custom X-CSRFToken header. This is described in the django docs: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax. However, since the use of jQuery.ajaxSetup is not recommended, it's probably better to do this by handling the ajaxSend event instead (see this example).
Comments