使用 Jinja 进行 Flask 模板流式传输

Posted

技术标签:

【中文标题】使用 Jinja 进行 Flask 模板流式传输【英文标题】:Flask template streaming with Jinja 【发布时间】:2015-01-13 15:46:45 【问题描述】:

我有一个烧瓶应用程序。在一个特定的视图中,我展示了一个总共有大约 100k 行的表格。页面加载需要很长时间是可以理解的,我正在寻找改进它的方法。到目前为止,我已经确定我查询数据库并很快得到结果。我认为问题在于渲染实际页面。我找到了this page on streaming 并正在尝试使用它,但一直遇到问题。我已经尝试过使用此代码提供的 stream_template 解决方案:

@app.route('/thing/matches', methods = ['GET', 'POST'])
@roles_accepted('admin', 'team')
def r_matches():
    matches = Match.query.filter(
            Match.name == g.name).order_by(Match.name).all()

    return Response(stream_template('/retailer/matches.html',
        dashboard_title = g.name,
        match_show_option = True,
        match_form = form,
        matches = matches))

def stream_template(template_name, **context):
    app.update_template_context(context)
    t = app.jinja_env.get_template(template_name)
    rv = t.stream(context)
    rv.enable_buffering(5)
    return rv

Match 查询是返回 100k+ 项的查询。但是,每当我运行此页面时,页面只会显示为空白,那里什么都没有。我还尝试了将数据流式传输到 json 并通过 ajax 加载它的解决方案,但 json 文件中似乎也没有任何内容!该解决方案如下所示:

@app.route('/large.json')
def generate_large_json():
    def generate():
        app.logger.info("Generating JSON")
        matches = Product.query.join(Category).filter(
            Product.retailer == g.retailer,
            Product.match != None).order_by(Product.name)
        for match in matches:
            yield json.dumps(match)
    app.logger.info("Sending file response")
    return Response(stream_with_context(generate()))

我正在寻找的另一个解决方案是分页。这个解决方案效果很好,除了我需要能够按标题对整个数据集进行排序,并且如果不将整个数据集呈现在表中然后使用 JQuery 进行排序/分页,就找不到这样做的方法。

我通过转到 /large.json 得到的文件总是空的。请帮助或推荐另一种显示如此大数据集的方式!

编辑:我让 generate() 部分工作并更新了代码。

【问题讨论】:

【参考方案1】:

这两种情况下的问题几乎可以肯定是您正在构建 100K+ Match 项目并将它们存储在内存中。您还需要使用yield_per 流式传输来自数据库的结果。但是,只有 PostGres+psycopg2 支持必要的stream_result 参数(here's a way to do it with mysql):

matches = Match.query.filter(
        Match.name == g.name).order_by(Match.name).yield_per(10)
        # Stream ten results at a time

另一种选择

如果您使用的是 Flask-SQLAlchemy,您可以利用其Pagination class 在服务器端对查询进行分页,而不是将所有 100K+ 条目加载到浏览器中。这有一个额外的好处,即不需要浏览器管理所有 DOM 条目(假设您正在执行 HTML 流选项)。

另见

SQLAlchemy: Scan huge tables using ORM? How to Use SQLAlchemy Magic to Cut Peak Memory and Server Costs in Half

【讨论】:

以上是关于使用 Jinja 进行 Flask 模板流式传输的主要内容,如果未能解决你的问题,请参考以下文章

flask基础之jinja2模板-语法定义

Flask Jinja2模板语言

当使用flask进行流式传输时,只有opencv的VIDEO错误。

Flask - 基本使用与配置

flask的模板

使用 Flask/Jinja2 将 HTML 传递给模板