I am writing a small flask based site and I would like to send data from the client to the server using Ajax. Until now I have only used Ajax requests to retrieve data from the server. This time I would like to submit data via POST request.
This is the receiver on the flask side, I reduced it to barely log a message to avoid any unnecessary errors within the implementation of this route:
@app.route("/json_submit", methods=["POST"])
def submit_handler():
# a = request.get_json(force=True)
app.logger.log("json_submit")
return {}
When submitting the ajax request, flask gives me a 400 error
127.0.0.1 - - [03/Apr/2014 09:18:50] "POST /json_submit HTTP/1.1" 400 -
I can also see this in the web developer console in the browser
Why is flask not calling submit_handler
with the supplied data in the request?
var request = $.ajax({
url: "/json_submit",
type: "POST",
data: {
id: id,
known: is_known
},
dataType: "json",
})
.done( function (request) {
})
If you are using the Flask-WTF CSRF protection you'll need to either exempt your view or include the CSRF token in your AJAX POST request too.
Exempting is done with a decorator:
@csrf.exempt
@app.route("/json_submit", methods=["POST"])
def submit_handler():
# a = request.get_json(force=True)
app.logger.log("json_submit")
return {}
To include the token with AJAX requests, interpolate the token into the page somewhere; in a <meta>
header or in generated JavaScript, then set a X-CSRFToken
header. When using jQuery, use the ajaxSetup
hook.
Example using a meta tag (from the Flask-WTF CSRF documentation):
<meta name="csrf-token" content="{{ csrf_token() }}">
and in your JS code somewhere:
var csrftoken = $('meta[name=csrf-token]').attr('content')
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
}
})
Your handler doesn't actually post JSON data yet; it is still a regular url-encoded POST
(the data will end up in request.form
on the Flask side); you'd have to set the AJAX content type to application/json
and use JSON.stringify()
to actually submit JSON:
var request = $.ajax({
url: "/json_submit",
type: "POST",
contentType: "application/json",
data: JSON.stringify({
id: id,
known: is_known
}),
})
.done( function (request) {
})
and now the data can be accessed as a Python structure with the request.get_json()
method.
The dataType: "json",
parameter to $.ajax
is only needed when your view returns JSON (e.g. you used flask.json.jsonify()
to produce a JSON response). It lets jQuery know how to process the response.
Can you try like this
var request = $.ajax({
url: "/json_submit",
type: "POST",
contentType: "application/json",
data: JSON.stringify({
id: id,
known: is_known
}),
dataType: "json",
})
.done( function (request) {
})
Before that, In your code returns dict object. That is not correct. It returns json like
@app.route("/json_submit", methods=["POST"])
def submit_handler():
# a = request.get_json(force=True)
app.logger.log("json_submit")
return flask.jsonify({'msg': 'success'})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With