New in version 0.9.
Flask 的設(shè)計(jì)思路之一是代碼有兩種不同的運(yùn)行“狀態(tài)”。一種是“安裝”狀態(tài),從 Flask 對(duì)象被實(shí)例化后開始,到第一個(gè)請(qǐng)求到來(lái)之前。在這種狀態(tài)下,以下規(guī)則 成立:
相反,在請(qǐng)求處理時(shí),以下規(guī)則成立:
除了上述兩種狀態(tài)之外,還有位于兩者之間的第三種狀態(tài)。這種狀態(tài)下,你正在處理應(yīng)用, 但是沒(méi)有活動(dòng)的請(qǐng)求。就類似于,你座在 Python 交互終端前,與應(yīng)用或一個(gè)命令行程序互動(dòng)。
應(yīng)用環(huán)境是 current_app 本地環(huán)境的源動(dòng)力。
應(yīng)用環(huán)境存在的主要原因是,以前過(guò)多的功能依賴于請(qǐng)求環(huán)境,缺乏更好的處理方案。 Flask 的一個(gè)重要設(shè)計(jì)原則是可以在同一個(gè) Pyhton 進(jìn)程中運(yùn)行多個(gè)應(yīng)用。
那么,代碼如何找到“正確”的應(yīng)用呢?以前我們推薦顯式地傳遞應(yīng)用,但是有可能會(huì)引發(fā)庫(kù)與庫(kù)之間的干擾。
問(wèn)題的解決方法是使用 current_app 代理。 current_app 是綁定到當(dāng)前請(qǐng)求的應(yīng)用的引用。但是沒(méi)有請(qǐng)求的情況下使用請(qǐng)求環(huán)境是一件奢侈在事情,于是就引入了應(yīng)用環(huán)境。
創(chuàng)建應(yīng)用環(huán)境有兩種方法。一種是隱式的:當(dāng)一個(gè)請(qǐng)求環(huán)境被創(chuàng)建時(shí),如果有需要就會(huì) 相應(yīng)創(chuàng)建一個(gè)應(yīng)用環(huán)境。因此,你可以忽略應(yīng)用環(huán)境的存在,除非你要使用它。
另一種是顯式的,使用 app_context() 方法:
from flask import Flask, current_app
app = Flask(__name__)
with app.app_context():
# 在本代碼塊中, current_app 指向應(yīng)用。
print current_app.name
在 SERVER_NAME 被設(shè)置的情況下,應(yīng)用環(huán)境還被 url_for() 函數(shù) 使用。這樣可以讓你在沒(méi)有請(qǐng)求的情況下生成 URL 。
應(yīng)用環(huán)境按需創(chuàng)建和消滅,它從來(lái)不在線程之間移動(dòng),也不被不同請(qǐng)求共享。因此,它是 一個(gè)存放數(shù)據(jù)庫(kù)連接信息和其他信息的好地方。內(nèi)部的棧對(duì)象被稱為 flask._app_ctx_stack 。擴(kuò)展可以在棧的最頂端自由儲(chǔ)存信息,前提是使用唯一 的名稱,而 flask.g 對(duì)象是留給用戶使用的。
更多信息參見 Flask 擴(kuò)展開發(fā) 。
環(huán)境的典型用途是緩存一個(gè)請(qǐng)求需要預(yù)備或使用的資源,例如一個(gè)數(shù)據(jù)庫(kù)連接。因?yàn)榄h(huán)境是一個(gè) Flask 的應(yīng)用和擴(kuò)展共享的地方,所以儲(chǔ)存的資源必須使用獨(dú)一無(wú)二的名稱。
最常見的用法是把資源管理分為以下兩個(gè)部分:
通常會(huì)有一個(gè)形如 get_X() 函數(shù),這個(gè)函數(shù)的用途是當(dāng)資源 X 存在時(shí)就返回 這個(gè)資源,否則就創(chuàng)建這個(gè)資源。還會(huì)有一個(gè) teardown_X() 函數(shù)用作解散句柄。
這是一個(gè)連接數(shù)據(jù)庫(kù)的例子:
import sqlite3
from flask import g
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = connect_to_database()
return db
@app.teardown_appcontext
def teardown_db(exception):
db = getattr(g, '_database', None)
if db is not None:
db.close()
第一次調(diào)用 get_db() 時(shí),連接將會(huì)被建立。建立的過(guò)程中隱式地使用了一個(gè) LocalProxy 類:
from werkzeug.local import LocalProxy
db = LocalProxy(get_db)
這樣,用戶就可以通過(guò) get_db() 來(lái)直接訪問(wèn) db 了。
? Copyright 2013, Armin Ronacher. Created using Sphinx.