Flask - 对 POST 的响应 - 令人困惑的行为

2024-03-26

我对 Flask 中的以下行为感到完全困惑。我确信发生了一些基本的事情,但我不知道这是脚本还是服务器问题,所以我发布了我能想到的最短的示例。

该页面有两种方式将数据发布到服务器。一种是通过提交<form>另一个是通过监听的脚本Ctrl+V。我相信两者都应该导致最后一个render_template call. But只有第一个可以。

粘贴.html

{%if msg %}
    {{ msg }}
{% else %}
Waiting
{% endif %}    
<form action="/pastetest" method="post">
      Dummy<br>
  <input type="text" name="foo" value="bar">
  <br>
  <input type="submit" value="Send info" />
</form>

Script侦听“粘贴”事件 (Ctrl V) 并在表单中发布一些虚拟字符串。

document.addEventListener('paste', function (e) {sendform(e);},false);
sendform = function (e) {
        var fd = new FormData();
        fd.append('data','testing paste');
        var request = new XMLHttpRequest();
        request.open("POST", "/pastetest");
        request.send(fd);
        console.log("Sent")
    };

FlaskPython:

@app.route('/')
def index():
    return render_template('paste.html',msg="Waiting")

@app.route('/pastetest',methods=['POST']) 
def image_upload():
    if request.method == 'POST':
        print("On the server")
        print(request.form)
        alldone="All done time=%d" % time.time()
        print(alldone)
        return redirect(url_for('confirm',msg=alldone))

@app.route('/confirm/<msg>')
def confirm(msg):
    print("At confirm",msg)
    return render_template("paste.html",msg=msg) #<---should end up here

从控制台我看到数据正在发布并且confirm正在被呼叫。127.0.0.1 - - [19/Nov/2017 00:51:42] "GET /confirm/All%20done%20time%3D1511049102 HTTP/1.1" 200 -

但页面仅在提交按钮后呈现。不然就卡在了Waiting.

Edit: 澄清一下:我需要的只是获取发布的数据(上面只是一个虚拟字符串,但将是剪贴板中的一个 blob),用它做一些事情,然后渲染一个包含结果的模板。做到这一点最简单的方法是什么?

(我对 js/客户端服务器等完全一无所知。只是想为我已经编写的图像分析程序制作一个简单的 Web 界面。简单的解释表示赞赏:)


它不会呈现您的页面,因为您只是发送一个XmlHttpRequest,仅此一项不会让您的浏览器呈现响应。

正如您从日志中看到的那样,您的 JavaScript 确实向指定的 URL 发送了 POST 请求,但由于您没有执行任何操作对该请求的响应 https://stackoverflow.com/questions/3038901/how-to-get-the-response-of-xmlhttprequest, 什么都没发生。

这会起作用...

<form action="/pastetest" method="post">

...因为提交 HTML 表单时,您的浏览器不仅仅是向以下 URL 发送 POST 请求action,它还会更改该 URL 的位置并呈现它所获得的响应。

您会注意到,提交 HTML 表单时,浏览器地址栏中的 URL 确实发生了变化,而发送您的 HTML 表单时却没有变化。XmlHttpRequest.

编辑,从评论中总结:

在这两种情况下,服务器都会执行这些功能image_upload and confirm,换句话说,从服务器的角度来看,它们是等效的,这里的主要区别在于,使用 XmlHttpRequest 方法时,浏览器不会自动呈现响应。

至于问题中描述的目标,让浏览器在两种情况下渲染结果页面,我们必须考虑在这两种情况下发生了什么XmlHttpRequest一旦我们得到回应:

  • 服务器已经执行的功能image_upload and confirm
  • 我们渲染的模板来自confirm函数在我们的响应中

如果我们不介意confirm函数被执行两次,我们可以简单地指出window.location我们的浏览器响应URL https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseURL的请求。

当我们这样做时,该函数肯定会被执行两次,它已经被执行了一次以生成我们得到的响应,并且让我们的浏览器转到responseURL(在我们的例子中,这将是与confirm函数),它将再次执行。

如果我们想防止这种情况发生,我们需要另一个解决方案。

一种选择是通知服务器我们在进行初始上传时不希望重定向到呈现的响应页面,而只需要状态信息(我们可以在此处使用 HTTP 状态代码,例如我们将 status=200 解释为成功)在我们上传时,服务器响应应该是我们需要指向的地方window.location我们的浏览器。

这样服务器就会执行confirm仅一次,因为在 XmlHttpRequest 的情况下它不会再自动重定向我们,相反,它只会告诉我们需要去哪里,并将实际去那里的责任留给客户端 JavaScript。

这意味着我们的服务器端代码需要改变,服务器需要辨别我们想要什么类型的响应。我们可以使用两个不同的上传端点来实现这一点,例如/pastetest对于表单提交,以及/pastetestxhr对于 XmlHttpRequest。

另一种选择是使用 JavaScript 从响应中提取渲染模板的部分内容,并替换当前页面的部分内容,就像从页面中删除 HTML 表单一样,并将其替换为响应中的成功通知。

为了以方便的方式做到这一点,我们可能需要使用一些客户端 JavaScript 库,例如jQuery.

这也只会执行confirm一次,因为在收到响应后我们不会将浏览器位置更改为该端点,而是使用我们已有的响应。

这种方法不需要更改任何服务器端代码,但会在客户端代码中引入更多复杂性。

第三种选择可能是混合方法,我们通知服务器我们不需要自动重定向,并期望我们可以将 HTML 片段作为响应插入到页面中,无需对响应进行任何复杂的解析来提取位以及我们想要插入到页面中的片段。

这需要稍微复杂一点的客户端 JavaScript(不过比上面列出的选项 2 复杂一些),以及服务器端代码更改。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flask - 对 POST 的响应 - 令人困惑的行为 的相关文章

随机推荐