【问题标题】:how can i send a POST request from jquery ajax to a flask view?如何将 POST 请求从 jquery ajax 发送到烧瓶视图?
【发布时间】:2018-04-05 15:55:50
【问题描述】:

希望你有一个美好的一天 :D 所以让我开始解释我要做的事情:我有一个 html 页面 (index.html) 和一个视图 (/index) index.html 页面在其中包含一个表单,提交时将使用 jquery ajax 发送一个 json /index 视图的对象 这是非常简单明了的 index.html 的代码:

<body>
<form action="/" method='post'>
    <button id='submit'>submit</button>
</form>

<script src="../static/jquery.min.js"></script>
<script>
    function saveMenu() {
        localStorage.setItem("shoppingMenu", JSON.stringify(
            [{"name":"*Kabab Combo Plate","price":10.99,"count":4},
            {"name":"Mixed Grill(Lamb, Chicken, Kefta)","price":14.99,"count":4}]
            ));
    };

    saveMenu();

    function loadMenu() {
        menu = JSON.parse(localStorage.getItem("shoppingMenu"));
        return menu;
    };
</script>
<script>
    $(document).ready(function() {
        var menu = JSON.stringify(loadMenu());
        $('#submit').click(function(){
            $.ajax({
                data: menu,
                dataType: 'json',
                type: 'POST',
                contentType: 'application/json; charset=utf-8',
                url: '{{ url_for("index") }}',
                success: function(m){
                        console.log(m);
                },
                error: function(m){
                    console.log(m);
                }
            });
        });
    });
</script>
</body>

这里是 /index 视图的代码,请注意我添加了打印语句,这是出于调试目的,您马上就会明白我的意思:

@app.route('/', methods=['POST', 'GET'])
def index():
    if request.method == 'POST':
        data = request.json
        print('header: ', request.headers.get('Content-Type'))
        print('data type: ', type(data))
        print('data = ', data)
        for i in data:
            print(i)
        return 'success'
    return render_template('index.html')

现在执行之前的代码时会发生什么:

* Debugger is active!
* Debugger PIN: 143-889-961
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [24/Oct/2017 21:12:20] "GET / HTTP/1.1" 200 -
header:  application/json; charset=UTF-8
data type:  <class 'list'>
data =  [{'name': '*Kabab Combo Plate', 'count': 4, 'price': 10.99}, {'name': 'Mixed Grill(Lamb, Chicken, Kefta)', 'count': 4, 'price': 14.99}]
{'name': '*Kabab Combo Plate', 'count': 4, 'price': 10.99}
{'name': 'Mixed Grill(Lamb, Chicken, Kefta)', 'count': 4, 'price': 14.99}
127.0.0.1 - - [24/Oct/2017 21:12:24] "POST / HTTP/1.1" 200 -
header:  application/x-www-form-urlencoded
data type:  <class 'NoneType'>
data =  None
127.0.0.1 - - [24/Oct/2017 21:12:24] "POST / HTTP/1.1" 500 -
Traceback (most recent call last):
  File "C:\Users\Orbit\flaskname\lib\site-packages\flask\app.py", line 1997, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:\Users\Orbit\flaskname\lib\site-packages\flask\app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "C:\Users\Orbit\flaskname\lib\site-packages\flask\app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\Orbit\flaskname\lib\site-packages\flask\_compat.py", line 33, in reraise
    raise value
  File "C:\Users\Orbit\flaskname\lib\site-packages\flask\app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "C:\Users\Orbit\flaskname\lib\site-packages\flask\app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:\Users\Orbit\flaskname\lib\site-packages\flask\app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:\Users\Orbit\flaskname\lib\site-packages\flask\_compat.py", line 33, in reraise
    raise value
  File "C:\Users\Orbit\flaskname\lib\site-packages\flask\app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:\Users\Orbit\flaskname\lib\site-packages\flask\app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:\Users\Orbit\flaskname\app\hello.py", line 25, in index
    for i in data:
TypeError: 'NoneType' object is not iterable
127.0.0.1 - - [24/Oct/2017 21:12:24] "GET /?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 200 -
127.0.0.1 - - [24/Oct/2017 21:12:24] "GET /?__debugger__=yes&cmd=resource&f=jquery.js HTTP/1.1" 200 -
127.0.0.1 - - [24/Oct/2017 21:12:24] "GET /?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 200 -
127.0.0.1 - - [24/Oct/2017 21:12:24] "GET /?__debugger__=yes&cmd=resource&f=ubuntu.ttf HTTP/1.1" 200 -
127.0.0.1 - - [24/Oct/2017 21:12:24] "GET /?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -

通过查看打印语句输出,在错误出现之前,请注意 request.json 工作正常并返回我们期望的数据,但随后出现 127.0.0.1 - - [24/Oct/2017 21:12:24] "POST / HTTP/1.1" 200 -,然后看起来视图函数是重新运行自身,然后打印语句输出 none 作为数据变量的值...有谁知道为什么会发生这种模式?以及如何解决?

【问题讨论】:

    标签: jquery python json ajax flask


    【解决方案1】:

    问题是,默认情况下,表单中的提交事件(在这种情况下,当您单击提交按钮时发生)将重定向到表单的action,因此,您实际上是做两个请求(ajax 和默认)。

    为防止这种情况发生,请在点击处理程序中触发 event.preventDefault(并将 event 添加到参数中)。

    .click(function(event) {
      // ...
      event.preventDefault()
    }
    

    您还需要从烧瓶视图返回一个 json 响应,如下所示:

    from flask import jsonify
    
    # ...
    
      return jsonify('success')
    

    【讨论】:

    • 非常感谢 :))。这防止了回溯错误。然而 ajax 正在记录错误函数 error: function(m){ console.log(m);} 以下是在记录的错误中保存值的参数:readyState: 4responseText: “success”status: 200status: “OK” 到目前为止,你已经帮助了我很多,但如果你知道为什么ajax 错误正在显示,或者如果我应该关心它,请告诉我。再次感谢^^
    • 这个问题是因为在请求中你要求 json 但返回一个字符串,所以 jQuery 抛出一个解析错误。要修复它,您应该从烧瓶视图返回 json。更新了答案以显示这一点。
    • “成功”现在在我提交表单时显示为警报。但正如你所知道的,我使用“成功”作为返回值,所以代码简单易懂。如何返回 render_template 或 redirect(url_for))?
    • 您是否更改了代码中的任何内容?您必须在某处使用警报才能成功显示为警报。在任何情况下,如果您使用的是 ajax,则返回 render_template 或重定向是没有意义的,因为您应该期望 json 返回;然后应该从 js 端触发路径更改或重定向。
    • 这是 ajax 内部的 success: function(m){ alert(m) },它返回了我从烧瓶视图返回的内容!你能告诉我如何从 js 改变路径,因为这是我感兴趣的
    【解决方案2】:

    您可以通过移除 html 模板中的表单来修复当前模式:

    <button id='submit'>submit</button>
    

    如果需要,让按钮单独放置或将其放在另一个部分中,但表单似乎提出了并行请求。我会尝试链接一些文档以更好地解释它。

    【讨论】:

    • 谢谢@PRMoureu,这是解决问题的一种方法,但我需要将表格用于其他目的,所以我保留它并使用preventDefault Luis 建议的那样,它会模拟没有形式。
    猜你喜欢
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-07
    • 2020-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多