1

In this Django project I'm building, I have data going back and forth between server and client via javascript and python using AJAX. For convenience I devised a config object in JS to carry over important parameters the server and responding JS need to know. On the Python side I am unable to access this object because it is None, but printing the object out to the JS console before sending and printing the POST object out to the Py console both show something is there. I don't understand why accessing the JS object (not it's memebers) in the QueryDict comes back as None.

# JavaScript   

var objConfig = {
   param1: "more text data",
   param2: "more text data",
   param3: "more text data",
};

console.log(objConfig);

$.ajax({
   type: "POST",
   url: url,
   data: {
      csrfmiddlewaretoken: strCsrfToken,
      strTextData: strTextData,
      objConfig: objConfig
   },
   success: callback
});

# JS console output:
# Object {param0: "more text data", param1: "more text data", param2: "more text data"}


# Python
def DoTheThing(response):
   print(response.POST.get('strTextData'))
   print(response.POST.get('objConfig'))
   print(response.POST)
   print(response.POST.get('objConfig[param0]'))

# Python console output:
# Text data being sent to server.
# None
# <QueryDict: {'csrfmiddlewaretoken': ['...'], 'strTextData': ['Text data being sent to server.'], 'objConfig[param0]': ['more text data'], 'objConfig[param1]': ['more text data'], 'objConfig[param2]': ['more text data']}>
# more text data

Notice how print(response.POST.get('objConfig')) prints None, but print(response.POST.get('objConfig[param0]')) prints exactly what I'd expect. I have also noticed in the QueryDict that it doesn't seem to have objObject represented as an object like how I was expecting. I understand to due differences between JS and Py objects, but it has each member of the object listed individually using an array index operator which I'm not sure why or how to use properly.

I can't just get the whole objConfig object, I need to access each member individually? Also how would this work trying to send objConfig in an HttpResponse? I devised the this kind of object pattern to save time and text space writing out each parameter individually for how I want this data to be handled going between server and client.

GhostRavenstorm
  • 634
  • 3
  • 9
  • 29

1 Answers1

3

The default Content-Type of $.ajax() is 'application/x-www-form-urlencoded; charset=UTF-8' the issue should be solved if you change it to application/json.

Example:

var data = {
    strTextData: strTextData,
    objConfig: objConfig
}

$.ajax({
   type: "POST",
   url: url,
   contentType : "application/json; charset=utf-8",
   headers: { "X-CSRFToken": strCsrfToken },
   data: JSON.stringify(data),
   success: callback
});

Check more info on the Jquery documentation

On you view you should:

import json
...
# on the view
data = json.loads(request.body)
dethos
  • 3,336
  • 1
  • 15
  • 15
  • I gave this a try and something goes awry with the CSRF token when I change the content type. It says "Forbidden (CSRF token missing or incorrect) just by adding that one line. Currently investigating. – GhostRavenstorm Sep 06 '18 at 17:52
  • Okay, so changing the content type is changing the CSRF Token I need to pass in for security reasons. – GhostRavenstorm Sep 06 '18 at 17:56
  • Just edited / fixed, but you can get more details on this answer: https://stackoverflow.com/questions/6506897/csrf-token-missing-or-incorrect-while-post-parameter-via-ajax-in-django – dethos Sep 06 '18 at 17:57
  • That works! But now there's no POST data when I print `request.POST` to the console. I found my data in `request.body` which is in a very strange format.

    `b'strTextData=Text%20data%20to%20be%20sent%20to%20server.&objConfig%5Bparam0%5D=more%20text%20data&objConfig%5Bparam1%5D=more%20text%20data&objConfig%5Bparam2%5D=more%20text%20data`
    – GhostRavenstorm Sep 06 '18 at 18:58
  • Added more info to the answer. To be have to handle the object with multiple layers of nested attributes you should parse the json content on the request body. – dethos Sep 06 '18 at 20:04