Where's my JSON data in my incoming Django request?
If you are posting JSON to Django, I think you want request.body
(request.raw_post_data
on Django < 1.4). This will give you the raw JSON data sent via the post. From there you can process it further.
Here is an example using JavaScript, jQuery, jquery-json and Django.
JavaScript:
var myEvent = {id: calEvent.id, start: calEvent.start, end: calEvent.end,
allDay: calEvent.allDay };
$.ajax({
url: '/event/save-json/',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: $.toJSON(myEvent),
dataType: 'text',
success: function(result) {
alert(result.Result);
}
});
Django:
def save_events_json(request):
if request.is_ajax():
if request.method == 'POST':
print 'Raw Data: "%s"' % request.body
return HttpResponse("OK")
Django < 1.4:
def save_events_json(request):
if request.is_ajax():
if request.method == 'POST':
print 'Raw Data: "%s"' % request.raw_post_data
return HttpResponse("OK")
I had the same problem. I had been posting a complex JSON response, and I couldn't read my data using the request.POST dictionary.
My JSON POST data was:
//JavaScript code:
//Requires json2.js and jQuery.
var response = {data:[{"a":1, "b":2},{"a":2, "b":2}]}
json_response = JSON.stringify(response); // proper serialization method, read
// http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
$.post('url',json_response);
In this case you need to use method provided by aurealus. Read the request.body and deserialize it with the json stdlib.
#Django code:
import json
def save_data(request):
if request.method == 'POST':
json_data = json.loads(request.body) # request.raw_post_data w/ Django < 1.4
try:
data = json_data['data']
except KeyError:
HttpResponseServerError("Malformed data!")
HttpResponse("Got json data")
Method 1
Client : Send as JSON
$.ajax({
url: 'example.com/ajax/',
type: 'POST',
contentType: 'application/json; charset=utf-8',
processData: false,
data: JSON.stringify({'name':'John', 'age': 42}),
...
});
//Sent as a JSON object {'name':'John', 'age': 42}
Server :
data = json.loads(request.body) # {'name':'John', 'age': 42}
Method 2
Client : Send as x-www-form-urlencoded
(Note: contentType
& processData
have changed, JSON.stringify
is not needed)
$.ajax({
url: 'example.com/ajax/',
type: 'POST',
data: {'name':'John', 'age': 42},
contentType: 'application/x-www-form-urlencoded; charset=utf-8', //Default
processData: true,
});
//Sent as a query string name=John&age=42
Server :
data = request.POST # will be <QueryDict: {u'name':u'John', u'age': 42}>
Changed in 1.5+ : https://docs.djangoproject.com/en/dev/releases/1.5/#non-form-data-in-http-requests
Non-form data in HTTP requests :
request.POST will no longer include data posted via HTTP requests with non form-specific content-types in the header. In prior versions, data posted with content-types other than multipart/form-data or application/x-www-form-urlencoded would still end up represented in the request.POST attribute. Developers wishing to access the raw POST data for these cases, should use the request.body attribute instead.
Probably related
- https://groups.google.com/forum/#!msg/django-developers/s8OZ9yNh-8c/yWeY138TpFEJ
- https://code.djangoproject.com/ticket/17942 . Fixed in 1.7
- http://homakov.blogspot.in/2012/06/x-www-form-urlencoded-vs-json-pros-and.html
Its important to remember Python 3 has a different way to represent strings - they are byte arrays.
Using Django 1.9 and Python 2.7 and sending the JSON data in the main body (not a header) you would use something like:
mydata = json.loads(request.body)
But for Django 1.9 and Python 3.4 you would use:
mydata = json.loads(request.body.decode("utf-8"))
I just went through this learning curve making my first Py3 Django app!
request.raw_response
is now deprecated. Use request.body
instead to process non-conventional form data such as XML payloads, binary images, etc.
Django documentation on the issue.