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