如何使用Python Flask下载生成器?

时间:2013-12-28 23:03:56

标签: python flask

我正在编写一个生成大量数据的应用程序,最终用户将下载这些数据(CSV文件)。我目前有一个页面,它根据表单中的条目生成数据,并将创建的生成器对象返回给用户,如下所示:

@app.route('/data', methods = ['GET', 'POST'])
def data():
    form = Form()
    if form.validate_on_submit():
        generator = create_generator(form)
        name = "results.csv"
        return Response(generator, mimetype="text/plain", headers={"Content-Disposition": "attachment;filename={}".format(name)})
    return render_template('data.html', title = 'Data Page', form = form)

现在,我想做的是将该生成器与一些其他数据一起传递到应用程序中的另一个视图/页面,如下所示:

@app.route('/data', methods = ['GET', 'POST'])
def data():
    form = Form()
    if form.validate_on_submit():
        generator, data = create_generator(form)
        name = "results.csv"
        #Can't send data in a redirect, but for example...
        redirect('/result', generator=generator, data=data, name=name)
    return render_template('data.html', title = 'Data Page', form = form)

@app.route('/output', methods = ['GET', 'POST'])
def output():
    form = Form()
    return render_template('output.html', title = 'Output Page', generator=generator, data=data, name=name)

其中output.html将有一个可点击的链接来下载生成器。换句话说,生成器不会像第一个带有return Response()的示例那样立即返回,而是等待用户。

总结一下,我要做的主要两件事是:

  1. 在页面之间传递生成器
  2. 将生成器作为标准链接返回 (<a href={{generator}}></a>或类似的东西)

1 个答案:

答案 0 :(得分:4)

HTTP协议是无状态的,你要求的是可撤销的。在您发出请求之前,服务器不知道您在做什么,而连接到客户端的唯一数据是沿请求发送的数据。

生成器是一个python对象,因此无法按照您的建议将其集成到HTML页面或链接中。您可以链接到使用生成器流式传输内容的应用程序的一部分,但不使用生成器作为链接,这没有任何意义。

您可以做的最接近的内容在以下代码段中进行了描述。没有编写实际的代码,我只是用评论来向您展示架构。

@app.route('/data', methods = ['GET', 'POST'])
def data():
    form = Form()
    if form.validate_on_submit():
        # Complete request
        # Generate data
        # Generate temp filename and save the result in it
        # Display (or redirect to) a page with a link to /get-result/{{ THE RESULT ID }}

    return render_template('data.html', title = 'Data Page', form = form)

@app.route('/get-result/<result_id>', methods = ['GET', 'POST'])
def output():
    # Open the result file based on its id
    # Stream it to the client as you did before