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

Popular posts from this blog

Handling control characters (escaping) in python for json and mysql

python port sniffer with pcapy and impacket

Django field, form and model validation process