由于坏json,ajax请求给出400错误

时间:2017-09-06 19:20:57

标签: python json ajax flask http-status-code-400

行!我正在构建一个烧瓶Web应用程序,我想使用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错误:

  • 来自here,据说:
  

HTTP 400错误请求响应状态代码表示由于语法无效,服务器无法理解请求。客户不应在未经修改的情况下重复此请求。

  • Csrf令牌丢失this我已经添加了令牌,并尝试使用csrf.exempt将数据发送到路由但没有
  • 未设置ContentType和applicationType(已经执行但没有设置)
  • 已经检查了他们所说的官方烧瓶文件:(来自)
  • 我正在发送正确的json数据
  • 那么可能导致这个问题??? 这是我的简单视图功能

    @ 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 ansynchrous的错误......

2 个答案:

答案 0 :(得分:0)

您不需要将数据转换为字符串:删除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将数据转换为字符串,因此您发布了一个字符串,没有JSON。

答案 1 :(得分:0)

好的,经过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并找到了烧瓶请求对象的这两行属性

  3.   

    is_json :   指示此请求是否为JSON。默认情况下,如果mimetype是application / json或application / * + json,则认为请求包含JSON数据。

      

    数据   包含传入的请求数据作为字符串,以防它带有mimetype Flask无法处理

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

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

    和VOILA !!!!获取200状态代码和数据作为python dict。