Reputation: 23
I would like to send some data from jQuery to a Tornado Python backend.
Here is simple example:
$.ajax({
url: '/submit_net',
dataType: 'json',
data: JSON.stringify({"test_1":"1","test_2":"2"}),
type: 'POST',
success: function(response) {
console.log(response);
},
error: function(error) {
console.log(error);
}
});
Here is the Python code:
class submit_net(tornado.web.RequestHandler):
def post(self):
data_json = self.request.arguments
print data_json
When I click the submit button then the Python backend retrieves following dictionary
{'{"test_1":"1","test_2":"2"}': ['']}
but I would like to retrieve exactly the same dictionary as jQuery sends:
{"test_1":"1","test_2":"2"}
Could you help me what I am doing wrong?
Upvotes: 0
Views: 3529
Reputation: 1122092
request.arguments
should only be used for form encoded data. Use request.body
to access the JSON raw data and decode with the json
module:
import json
data_json = self.request.body
data = json.loads(data_json)
request.body
contains bytes, which is fine in Python 2, but if you are using Python 3 you need to decode those to Unicode first. Get the request character-set with cgi.parse_header()
:
from cgi import parse_header
content_type = self.request.headers.get('content-type', '')
content_type, params = parse_header(content_type)
charset = params.get('charset', 'UTF8')
data = json.loads(data_json.decode(charset))
This defaults to the UTF-8 character set, which as a default is only valid for JSON requests; other request content types would need to be handled differently.
You may want to make it clear that you are sending a JSON body by setting the content type:
$.ajax({
url: '/submit_net',
contentType: "application/json; charset=utf-8",
data: JSON.stringify({"test_1":"1","test_2":"2"}),
type: 'POST',
success: function(response) {
console.log(response);
},
error: function(error) {
console.log(error);
}
});
and verify in your Tornado POST handler that that content type is being used before trying to decode the POST as JSON:
content_type = self.request.headers.get('content-type', '')
content_type, params = parse_header(content_type)
if content_type.lower() != 'application/json':
# return a 406 error; not the right content type
# ...
charset = params.get('charset', 'UTF8')
data = json.loads(data_json.decode(charset))
The $.ajax
dataType
parameter is only needed when you are returning JSON from Python back to jQuery; it tells jQuery to decode the response for you. This is not strictly needed even then, as a application/json
response Content-Type header is enough.
Upvotes: 2