max max - 6 months ago 19
JSON Question

what is the proper way to send and receive json requests in django

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)?


Answer

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);
        }
    }
});