显示Flask视图更新时的数据流

2024-04-25 09:57:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个生成数据并实时流化它的视图。我不知道如何将这些数据发送到我可以在HTML模板中使用的变量。我当前的解决方案只是在数据到达时将其输出到一个空白页,这是可行的,但我希望将其包含在具有格式的较大页中。当数据流到页面时,如何更新、格式化和显示数据?

import flask
import time, math

app = flask.Flask(__name__)

@app.route('/')
def index():
    def inner():
        # simulate a long process to watch
        for i in range(500):
            j = math.sqrt(i)
            time.sleep(1)
            # this value should be inserted into an HTML template
            yield str(i) + '<br/>\n'
    return flask.Response(inner(), mimetype='text/html')

app.run(debug=True)

Tags: 数据import视图模板appflasktimedef
1条回答
网友
1楼 · 发布于 2024-04-25 09:57:06

您可以在响应中流式传输数据,但不能像描述的那样动态更新模板。模板在服务器端呈现一次,然后发送到客户端。您需要使用JavaScript读取流式响应并在客户端输出数据。

使用XMLHttpRequest向将流式传输数据的终结点发出请求。然后定期从流中读取,直到完成为止。

本例假设一种非常简单的消息格式:一行数据,后跟一个换行符。当然,只要有一种方法来识别每一条消息,您就可以随心所欲地进行复杂的解析。例如,您可以返回一个JSON对象并在客户端对其进行解码。

from time import sleep
from flask import Flask, render_template
from math import sqrt

app = Flask(__name__)

@app.route('/')
def index():
    # render the template (below) that will use JavaScript to read the stream
    return render_template('index.html')

@app.route('/stream_sqrt')
def stream():
    def generate():
        for i in range(500):
            yield '{}\n'.format(sqrt(i))
            sleep(1)

    return app.response_class(generate(), mimetype='text/plain')

app.run()
<p>This is the latest output: <span id="latest"></span></p>
<p>This is all the output:</p>
<ul id="output"></ul>
<script>
    var latest = document.getElementById('latest');
    var output = document.getElementById('output');

    var xhr = new XMLHttpRequest();
    xhr.open('GET', '{{ url_for('stream') }}');
    xhr.send();
    var position = 0;

    function handleNewData() {
        // the response text include the entire response so far
        // split the messages, then take the messages that haven't been handled yet
        // position tracks how many messages have been handled
        // messages end with a newline, so split will always show one extra empty message at the end
        var messages = xhr.responseText.split('\n');
        messages.slice(position, -1).forEach(function(value) {
            latest.textContent = value;  // update the latest value in place
            // build and append a new item to a list to log all output
            var item = document.createElement('li');
            item.textContent = value;
            output.appendChild(item);
        });
        position = messages.length - 1;
    }

    var timer;
    timer = setInterval(function() {
        // check the response for new data
        handleNewData();
        // stop checking once the response has ended
        if (xhr.readyState == XMLHttpRequest.DONE) {
            clearInterval(timer);
            latest.textContent = 'Done';
        }
    }, 1000);
</script>

相关问题 更多 >