ajax 请求给出 400 错误,烧瓶坏了 json

ajax request give 400 error with flask due bad json

好的!!我正在构建一个烧瓶网络应用程序,我想使用 Ajax 发送一些 json 数据 这是我的代码!!对于 HTML 和 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>

我已经尝试了所有可能的方法,但仍然出现 400 错误! 我检查了所有相关问题,但没有。

但我的研究表明 400 错误可能是由此引起的:

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 "

请注意,在我的测试中,当我通过 python 将数据直接发送到我的路由时,它可以使用以下代码:

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:我确定我遗漏了一些东西但不知道是什么,也许 ajax 异步有问题......

您不需要将数据转换为字符串:删除 JSON.stringify:

$.ajax({
    cache: false,
    url : "{{url_for('predict')}}",
    type: "POST",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    data : data,
    success : function(callback){
        //Where $(this) => context == FORM
              console.log("data sucessfuly submitted")
              console.log(JSON.parse(callback));
    },
    error : function(){
        console.log('erroor')
    }
});

JSON.stringify你把你的数据转换成一个字符串,所以你post一个字符串,没有JSON。

好的,经过 7 天的调试,我找到了解决问题的方法: 我做了两件事:

  1. 从现在开始,为了我未来的网络开发 我将停止使用 jquery,我相信很快我就会找到充分的理由那 , 所以对于我的代码,我决定使用纯 javascript,这是我用来发送请求的代码:

    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 ')
    };
    };
    

    这是针对 javascript 部分的,我确信我正在向我的服务器发送良好的 json 对象

  2. 我去here看了flask官方文档,找到了flask请求对象的这两行属性

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.

data Contains the incoming request data as string in case it came with a mimetype Flask does not handle

并将我的后端代码更改为:

@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 "

瞧!!!!获取 200 状态代码和数据作为 python 字典。