I'm trying to process incoming JSON/Ajax requests with Django/Python.
request.is_ajax()
is True
on the request, but I have no idea where the payload is with the JSON data.
request.POST.dir
contains this:
['__class__', '__cmp__', '__contains__', '__copy__', '__deepcopy__', '__delattr__',
'__delitem__', '__dict__', '__doc__', '__eq__', '__ge__', '__getattribute__',
'__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__',
'__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__setitem__', '__str__', '__weakref__', '_assert_mutable', '_encoding',
'_get_encoding', '_mutable', '_set_encoding', 'appendlist', 'clear', 'copy', 'encoding',
'fromkeys', 'get', 'getlist', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues',
'keys', 'lists', 'pop', 'popitem', 'setdefault', 'setlist', 'setlistdefault', 'update',
'urlencode', 'values']
There are apparently no keys in the request post keys.
When I look at the POST in Firebug, there is JSON data being sent up in the request.
This question is related to
python
ajax
json
django
content-type
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!
html code
file name : view.html
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#mySelect").change(function(){
selected = $("#mySelect option:selected").text()
$.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
url: '/view/',
data: {
'fruit': selected
},
success: function(result) {
document.write(result)
}
});
});
});
</script>
</head>
<body>
<form>
<br>
Select your favorite fruit:
<select id="mySelect">
<option value="apple" selected >Select fruit</option>
<option value="apple">Apple</option>
<option value="orange">Orange</option>
<option value="pineapple">Pineapple</option>
<option value="banana">Banana</option>
</select>
</form>
</body>
</html>
Django code:
Inside views.py
def view(request):
if request.method == 'POST':
print request.body
data = request.body
return HttpResponse(json.dumps(data))
on django 1.6 python 3.3
client
$.ajax({
url: '/urll/',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(json_object),
dataType: 'json',
success: function(result) {
alert(result.Result);
}
});
server
def urll(request):
if request.is_ajax():
if request.method == 'POST':
print ('Raw Data:', request.body)
print ('type(request.body):', type(request.body)) # this type is bytes
print(json.loads(request.body.decode("utf-8")))
Something like this. It's worked: Request data from client
registerData = {
{% for field in userFields%}
{{ field.name }}: {{ field.name }},
{% endfor %}
}
var request = $.ajax({
url: "{% url 'MainApp:rq-create-account-json' %}",
method: "POST",
async: false,
contentType: "application/json; charset=utf-8",
data: JSON.stringify(registerData),
dataType: "json"
});
request.done(function (msg) {
[alert(msg);]
alert(msg.name);
});
request.fail(function (jqXHR, status) {
alert(status);
});
Process request at the server
@csrf_exempt
def rq_create_account_json(request):
if request.is_ajax():
if request.method == 'POST':
json_data = json.loads(request.body)
print(json_data)
return JsonResponse(json_data)
return HttpResponse("Error")
The HTTP POST payload is just a flat bunch of bytes. Django (like most frameworks) decodes it into a dictionary from either URL encoded parameters, or MIME-multipart encoding. If you just dump the JSON data in the POST content, Django won't decode it. Either do the JSON decoding from the full POST content (not the dictionary); or put the JSON data into a MIME-multipart wrapper.
In short, show the JavaScript code. The problem seems to be there.
request.POST is just a dictionary-like object, so just index into it with dict syntax.
Assuming your form field is fred, you could do something like this:
if 'fred' in request.POST:
mydata = request.POST['fred']
Alternately, use a form object to deal with the POST data.
request.raw_post_data
has been deprecated. Use request.body
instead
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
Using Angular you should add header to request or add it to module config
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
$http({
url: url,
method: method,
timeout: timeout,
data: data,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
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")
request.raw_response
is now deprecated. Use request.body
instead to process non-conventional form data such as XML payloads, binary images, etc.
Source: Stackoverflow.com