繁体   English   中英

Flask 和 Ajax 发布 HTTP 400 错误请求错误

[英]Flask and Ajax Post HTTP 400 Bad Request Error

我正在编写一个基于小烧瓶的站点,我想使用 Ajax 将数据从客户端发送到服务器。 到目前为止,我只使用 Ajax 请求从服务器检索数据。 这次我想通过POST请求提交数据。

这是烧瓶端的接收器,我将其简化为几乎不记录消息,以避免在此路由的实现中出现任何不必要的错误:

@app.route("/json_submit", methods=["POST"])
def submit_handler():
    # a = request.get_json(force=True)
    app.logger.log("json_submit")
    return {}

提交ajax请求时,flask给我400错误

127.0.0.1 - - [03/Apr/2014 09:18:50] "POST /json_submit HTTP/1.1" 400 -

我也可以在浏览器的 Web 开发者控制台中看到这一点

为什么flask没有使用请求中提供的数据调用submit_handler

 var request = $.ajax({
    url: "/json_submit",
    type: "POST",
    data: {
      id: id, 
      known: is_known
    },  
    dataType: "json",
  })  
   .done( function (request) {
  })

如果您使用Flask-WTF CSRF 保护,则需要在 AJAX POST 请求中免除您的视图或包含 CSRF 令牌。

豁免是通过装饰器完成的:

@csrf.exempt
@app.route("/json_submit", methods=["POST"])
def submit_handler():
    # a = request.get_json(force=True)
    app.logger.log("json_submit")
    return {}

要将令牌包含在 AJAX 请求中,请将令牌插入页面的某个位置; <meta>标头或生成的 JavaScript 中,然后设置X-CSRFToken标头。 使用 jQuery 时,请使用ajaxSetup hook

使用元标记的示例(来自 Flask-WTF CSRF 文档):

<meta name="csrf-token" content="{{ csrf_token() }}">

并在您的 JS 代码中:

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

您的处理程序实际上还没有发布 JSON 数据; 它仍然是一个常规的 url 编码的POST (数据将在 Flask 端的request.form结束); 您必须将 AJAX 内容类型设置为application/json并使用JSON.stringify()来实际提交 JSON:

var request = $.ajax({
   url: "/json_submit",
   type: "POST",
   contentType: "application/json",
   data: JSON.stringify({
     id: id, 
     known: is_known
   }),  
})  
  .done( function (request) {
})

现在可以使用request.get_json()方法将数据作为 Python 结构访问。

dataType: "json", $.ajax参数仅在您的视图返回JSON 时才需要(例如,您使用flask.json.jsonify()生成 JSON 响应)。 它让 jQuery 知道如何处理响应。

你可以这样试试吗

var request = $.ajax({
    url: "/json_submit",
    type: "POST",
    contentType: "application/json",
    data: JSON.stringify({
      id: id, 
      known: is_known
    }),  
    dataType: "json",
  })  
   .done( function (request) {
 })

在此之前,在您的代码中返回 dict 对象。 那是不正确的。 它返回 json 就像

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

不需要jQuery的类似解决方案

<meta name="csrf-token" content="{{ csrf_token() }}">

var beforeSend = function(xhr) {
    var csrf_token = document.querySelector('meta[name=csrf-token]').content;
    xhr.setRequestHeader("X-CSRFToken", csrf_token);
};

function fooFunction() {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "/json-submit");
    xhr.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            // Do what you want with this.responseText
        }
    };
    beforeSend(xhr);
    xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
    xhr.send(JSON.stringify({
        'id': id, 'known': is_known
    }));
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM