简体   繁体   English

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

[英]Flask - response to a POST - confusing behaviour

I am completely confused by the following behaviour in Flask. 我对Flask中的以下行为完全感到困惑。 I am sure there is something basic going on but I don't know if this is a script or a server issue, so I posted the shortest example I could come up with. 我确定发生了一些基本的事情,但是我不知道这是脚本还是服务器问题,因此我发布了我能想到的最短的示例。

The page has two ways to post data to the server. 该页面有两种将数据发布到服务器的方式。 One is triggered by submitting a <form> and the other by a script that listens for Ctrl+V . 一个是通过提交<form>触发的,另一个是通过侦听Ctrl+V的脚本触发的。 I believe both should lead to the last render_template call. 我相信两者都应导致最后一次render_template调用。 But only the first one does. 但是只有第一个。

paste.html paste.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 Listens for a 'paste' event (Ctrl V) and posts some dummy string in a form. 脚本侦听“粘贴”事件(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")
    };

Flask python: 烧瓶 python:

@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

From the console I see that the data is being posted and confirm is being called. 从控制台中,我看到正在发布数据并confirm正在调用。 127.0.0.1 - - [19/Nov/2017 00:51:42] "GET /confirm/All%20done%20time%3D1511049102 HTTP/1.1" 200 -

but the page only renders after the submit button. 但是页面仅在“提交”按钮之后呈现。 Otherwise it is stuck on Waiting . 否则,它将停留在Waiting

Edit : To clarify: all I need is to get the posted data (just a dummy string above but will be a blob from the clipboard), do something with it and then render a template with the results. 编辑 :澄清一下:我所需要做的就是获取发布的数据(上面只是一个虚拟字符串,但将是剪贴板中的Blob),对其进行处理,然后使用结果呈现模板。 What is the easiest way to do this? 最简单的方法是什么?

(I'm totally ignorant about js/client-server etc. Just trying to make a simple web interface for a image-analysis program that I already wrote. Simple explanations appreciated :) (我对js / client-server等一无所知。只是尝试为我已经编写的图像分析程序创建一个简单的Web界面。简单的解释表示赞赏:)

It does not render your page since you are just sending an XmlHttpRequest , that alone will not have your browser rendering the response. 由于您只是发送XmlHttpRequest ,因此它不会呈现您的页面,仅此而已就不会让您的浏览器呈现响应。

Your JavaScript does send a POST request to the URL specified as you can see from your logs, but since you are not doing anything with the response to that request , nothing happens. 您的JavaScript确实将POST请求发送到您从日志中看到的指定URL,但是由于您对该请求的响应未做任何事情, 因此没有任何反应

This will work... 这将起作用...

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

...because with submitting your HTML form, your browser is not just sending a POST request to the URL in action , it will also change location to that URL and render the response it is getting. ......因为提交HTML表单,您的浏览器不只是发送POST请求的URL action ,它也将改变位置到该网址,并使其越来越响应。

You'll notice that when submitting the HTML form, the URL in your browser location bar does change, which it doesn't when sending your XmlHttpRequest . 您会注意到,提交HTML表单时,浏览器位置栏中的URL确实发生了变化,而发送XmlHttpRequest时却没有变化。

Edit, summarizing from comments: 编辑,从评论中总结:

In both cases, the server will execute the functions image_upload and confirm , in other words from the server perspective, they are equivalent, the main difference here is that with the XmlHttpRequest method, the response is not automatically rendered by the browser. 在这两种情况下,服务器都会执行image_upload函数并confirm ,换句话说,从服务器角度来看,它们是等效的,主要区别在于使用XmlHttpRequest方法时,浏览器不会自动呈现响应。

As for the goal described in the question, having the browser render the result page in both cases, we have to think about what happened in the XmlHttpRequest case once we have our response: 至于问题中描述的目标,在两种情况下都让浏览器呈现结果页面,一旦获得响应,我们就必须考虑XmlHttpRequest情况发生了什么:

  • the server already executed functions image_upload and confirm 服务器已执行功能image_uploadconfirm
  • our rendered template from the confirm function is in our response 我们从confirm函数中渲染的模板在我们的响应中

In case we do not mind the confirm function being executed twice, we could simply point window.location of our browser to the responseURL of the request. 如果我们不介意两次执行confirm函数,则只需将浏览器的window.location指向请求的responseURL即可

The function will definitely be executed twice when we do this though, it has already been executed once in order to generate the response we got, and having our browser go to the responseURL (in our case, that will be the URL corresponding to the confirm function), it will execute again. 不过,执行此功能时,该函数肯定会执行两次,它已经执行过一次以生成我们收到的响应,并让我们的浏览器转到responseURL(在我们的示例中,这将是与confirm对应的URL函数),它将再次执行。

If we wanted to prevent this, we would need another solution though. 如果我们想防止这种情况,我们将需要另一种解决方案。

One option would be to inform the server that we do not want a redirect to the rendered response page when doing our initial upload, but instead just want a status information (we could use HTTP status code here, eg we interpret status=200 as success) on our upload, and the server response should be where we need to point window.location of our browser. 一种选择是通知服务器,我们在进行初始上传时不希望重定向到呈现的响应页面,而只是想要状态信息(我们可以在此处使用HTTP状态代码,例如,将status = 200解释为成功)上载,服务器响应应该是我们需要指向浏览器的window.location的位置。

This way, the server would execute confirm only once, as it would not automatically redirect us anymore in case of our XmlHttpRequest, instead it would just tell us where we need to go and leave the responsibility to actually go there to the client-side JavaScript. 这样,服务器将只执行一次confirm ,因为在XmlHttpRequest的情况下它将不再自动重定向我们,而是仅告诉我们我们需要去哪里,而将实际去那里的责任留给客户端JavaScript。 。

This would mean a change of our server-side code, the server would need to discern what type of response we want. 这将意味着更改我们的服务器端代码,服务器将需要识别我们想要哪种类型的响应。 We could implement this with two different endpoints for our upload, eg /pastetest for form submit, and /pastetestxhr for XmlHttpRequest. 我们可以使用两个不同的端点来实现此目的,例如, /pastetest用于表单提交, /pastetestxhr用于XmlHttpRequest。

Another option would be to extract parts of the rendered template from the response using JavaScript, and replace parts of our current page, as in remove our HTML form from the page, and replace it with our success notification from the response. 另一个选择是使用JavaScript从响应中提取呈现的模板的一部分,并替换当前页面的一部分,例如从页面中删除HTML表单,然后将其替换为响应中的成功通知。

In order to do this in a convenient way, we will likely want to use some client side JavaScript libraries such as jQuery . 为了方便地进行此操作,我们可能希望使用一些客户端JavaScript库,例如jQuery

This would also only execute confirm once, as we would refrain from changing browser location to that endpoint after we got our response, and instead use the response we already have. 这也只会执行一次confirm ,因为我们将避免在收到响应后将浏览器位置更改为该端点,而是使用已经拥有的响应。

This approach does not require any server-side code to be changed, but introduce more complexity in our client-side code. 这种方法不需要更改任何服务器端代码,但是会在我们的客户端代码中引入更多的复杂性。

A third option could be a hybrid approach, we inform the server that we do not want an automatic redirect, and expect as a response an HTML snippet we can insert in our page as is, without any complex parsing of the response to extract the bits and pieces we want to insert into our page. 第三种选择是混合方法,我们通知服务器我们不希望自动重定向,并希望作为响应的HTML代码片段可以原样插入页面中,而无需对响应进行任何复杂的解析来提取位以及我们想要插入页面的片段。

This one would require a litte more complex client-side JavaScript (less complex than our option 2 lined out above though), and server-side code change. 这需要一个复杂得多的客户端JavaScript(尽管比上面列出的选项2复杂得多),并且需要更改服务器端代码。

The browser will not render the response from XmlHttpRequest unless you tell the browser via JS to do so. 除非您通过JS告诉浏览器这样做,否则浏览器将不会呈现XmlHttpRequest的响应。 I suggest you take a look at the 'Development Tools' of your browser and check under the Network tab. 建议您查看浏览器的“开发工具”,然后在“网络”标签下进行检查。 You will see your XHR's response in there but it will not replace the content or your browser. 您将在此处看到XHR的响应,但不会替换内容或浏览器。

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

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