Ok!! I'm building a flask web app, and I want to use Ajax to send some json data Here is my code!! for the HTML and js :
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Check your Grades</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="{{ url_for('static', filename='js/bootstrap3-typeahead.min.js')}}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/index.js')}}"></script>
<link rel="stylesheet" href="{{url_for('static', filename='css/style.css')}}">
</head>
<body>
<link href='https://fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'>
<form id="predict-form" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<p> welcome to grade predictor app,</p>
<p>Dear Plateform,</p>
<p>je viens
<label for="SCHOOL_RIGHT"> de </label>
<input class="typeahead" type="text" name="SCHOOL_RIGHT" id="SCHOOL_RIGHT" minlength="3" placeholder="(votre ecole de provenance)" data-provide="typeahead" autocomplete="off" required> et </p>
<p>dans
<label for="OPTION_RIGHT">l'option</label>
<input class="typeahead"
name="OPTION_RIGHT" id="OPTION_RIGHT" data-provide="typeahead" placeholder="(choisissez votre option )" required>
</p>
<p>j'ai obtenu
<label for="DIPPERC"></label>
<input type="number" name="DIPPERC" min="50" max="100" id="DIPPERC" placeholder="(Poucentage du
diplome )" required> % à l\'exetat
</p>
<p>
<button type="submit">
<svg version="1.1" class="send-icn" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="100px" height="36px" viewBox="0 0 100 36" enable-background="new 0 0 100 36" xml:space="preserve">
<path d="M100,0L100,0 M23.8,7.1L100,0L40.9,36l-4.7-7.5L22,34.8l-4-11L0,30.5L16.4,8.7l5.4,15L23,7L23.8,7.1z M16.8,20.4l-1.5-4.3
l-5.1,6.7L16.8,20.4z M34.4,25.4l-8.1-13.1L25,29.6L34.4,25.4z M35.2,13.2l8.1,13.1L70,9.9L35.2,13.2z" />
</svg>
<small>send</small>
</button>
</p>
</form>
<script >
var csrf_token = "{{ csrf_token() }}";
// this will send a token each time before a session started
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrf_token);
}
}
});
//submit form data
$("form#predict-form").submit(function(e){
console.log("form submitted")
e.preventDefault();
var data = {
}
var Form = this;
//Gathering the Data
//and removing undefined keys(buttons)
$.each(this.elements, function(i, v){
var input = $(v);
data[input.attr("name")] = input.val();
delete data["csrf_token"];
delete data["undefined"];
});
data["DIPPERC"] = data["DIPPERC"]/100.0
//Form Validation goes here....
//Save Form Data........
$.ajax({
cache: false,
url : "{{url_for('predict')}}",
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
data : JSON.stringify(data),
success : function(callback){
//Where $(this) => context == FORM
console.log("data sucessfuly submitted")
console.log(JSON.parse(callback));
}
,
error : function(){
console.log('erroor')
}
});
})
</script>
</body>
</html>
I've tried everything possible but still getting the 400 error! I've checked all related questions but nothing.
But my research shows that the 400 error can be caused by this according to :
The HTTP 400 Bad Request response status code indicates that the server could not understand the request due to invalid syntax. The client should not repeat this request without modification.
@predictions.route('/predictions/predict/', methods=['GET', 'POST'])
def predict():
if request.method == 'POST':
print "hello----------------------"
print request.method
print request.get_json(force=True)
return "done "
Note in my test when I send directly data via python to my route it works with this code :
def test_1_can_connect_post(self):
"""
Test API can create a (POST request)
"""
new_student = {
'DIPPERC':0.60, 'SCHOOL_RIGHT':'itfm/bukavu', 'OPTION_RIGHT':'elec indust'
}
res = self.client().post('predictions/predict/', data=json.dumps(new_student), content_type='application/json')
self.assertEqual(res.status_code, 201)
Ps: I'm sure that I'm missing a little thing but don't know what, maybe something wrong with ajax asynchronous .....
Ok , after 7 days of debugging i just found a solution for my problem : i do two things:
from now and for my future web development i will stop using jquery and I'm sure that soon i will found good reason for that , so for my code i decide to use plain javascript and here is the code i use to send the request :
var csrf_token = "{{ csrf_token() }}";
// this will send a token each time before a session started
var form = document.getElementById("predict-form");
form.onsubmit = function (e) {
// stop the regular form submission
e.preventDefault();
// collect the form data while iterating over the inputs
var formEntries = new FormData(form).entries();
var data = Object.assign(...Array.from(formEntries, ([x,y]) => ({[x]:y})));
delete data["csrf_token"];
data["DIPPERC"] = data["DIPPERC"]/100.0
console.log(data);
// construct an HTTP request
var xhr = new XMLHttpRequest();
xhr.open(form.method, form.action, true);
xhr.setRequestHeader("X-CSRFToken", csrf_token);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
// send the collected data as JSON
xhr.send(JSON.stringify(data));
xhr.onloadend = function () {
console.log('blallala ')
};
};
this was for the javascript part and I was sure that i was sending good json object to my server
i went here at flask official documentation and found these 2 lines of attributes of flask request object
is_json : Indicates if this request is JSON or not. By default a request is considered to include JSON data if the mimetype is application/json or application/*+json.
and
data Contains the incoming request data as string in case it came with a mimetype Flask does not handle
and change my backend code to this :
@predictions.route('/predictions/predict/', methods=['GET', 'POST'])
def predict():
"""
the main methode use to predict
"""
if request.method == 'POST':
print "hello----------------------"
print request.is_json
print request.data
print '-----------------------------------------'
return "done "
And VOILA!!!! get the 200 status code and the data as a python dict.