使用 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 模板流式传输的主要内容,如果未能解决你的问题,请参考以下文章