W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
有時,您希望發(fā)送非常巨量的數(shù)據(jù)到客戶端,遠遠超過您可以保存在內(nèi)存中的量。 在您實時地產(chǎn)生這些數(shù)據(jù)時,如何才能直接把他發(fā)送給客戶端,而不需要在文件 系統(tǒng)中中轉(zhuǎn)呢?
答案是生成器和 Direct Response。
下面是一個簡單的視圖函數(shù),這一視圖函數(shù)實時生成大量的 CSV 數(shù)據(jù), 這一技巧使用了一個內(nèi)部函數(shù),這一函數(shù)使用生成器來生成數(shù)據(jù),并且 稍后激發(fā)這個生成器函數(shù)時,把返回值傳遞給一個 response 對象:
from flask import Response
@app.route('/large.csv')
def generate_large_csv():
def generate():
for row in iter_all_rows():
yield ','.join(row) + '\n'
return Response(generate(), mimetype='text/csv')
每一個 yield 表達式直接被發(fā)送給瀏覽器?,F(xiàn)在,仍然有一些 WSGI 中間件可能 打斷數(shù)據(jù)流,所以在這里請注意那些在帶緩存快照的調(diào)試環(huán)境,以及其他一些您可能 激活了的東西。
Jinja2 模板引擎同樣支持分塊逐個渲染模板。Flask 沒有直接暴露這一功能到 模板中,因為它很少被用到,但是您可以很輕易的自己實現(xiàn):
from flask import Response
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
@app.route('/my-large-page.html')
def render_large_template():
rows = iter_all_rows()
return Response(stream_template('the_template.html', rows=rows))
這一技巧是從應用程序上的 Jinja2 的環(huán)境中得到那個模板對象,然后調(diào)用 stream() 函數(shù)而不是 render() 函數(shù)。前者返回的是一個流對象,而不是后者的字符串。因為我們繞過了 Flask 的模板渲染函數(shù),而是直接使用了模板對象,所以我們手動必須調(diào)用 update_template_context() 函數(shù)來確保更新了模板的渲染上下文。 這一模板隨后以流的方式迭代直到結(jié)束。因為每一次您使用使用一個 yield 。服務器 都會將所有的已經(jīng)產(chǎn)生的內(nèi)容塞給給客戶端,因可能希望在模板中緩沖一部分元素 之后再發(fā)送,而不是每次都直接發(fā)送。您可以使用 rv.enable_buffering(size) 來實現(xiàn),size 的較為合理的默認值是 5 。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: