Flask中有兩種上下文,請求上下文和應用上下文。
請求上下文(request context)
request和session都屬於請求上下文對象。
request:封裝了HTTP請求的內容,針對的是http請求。舉例:user = request.args.get('user'),獲取的是get請求的參數。
session:用來記錄請求會話中的信息,針對的是用戶信息。舉例:session['name'] = user.id,可以記錄用戶信息。還可以通過session.get('name')獲取用戶信息。
應用上下文(application context)
current_app和g都屬於應用上下文對象。
current_app:表示當前運行程序文件的程序實例。
g:處理請求時,用於臨時存儲的對象,每次請求都會重設這個變量。比如:我們可以獲取一些臨時請求的用戶信息。
- 當調用app = Flask(_name_)的時候,創建了程序應用對象app;
- request 在每次http請求發生時,WSGI server調用Flask.call();然後在Flask內部創建的request對象;
- app的生命週期大於request和g,一個app存活期間,可能發生多次http請求,所以就會有多個request和g。
- 最終傳入視圖函數,通過return、redirect或render_template生成response對象,返回給客戶端。
區別: 請求上下文:保存了客戶端和服務器交互的數據。 應用上下文:在flask程序運行過程中,保存的一些配置信息,比如程序文件名、數據庫的連接、用戶信息等。
上下文對象的作用域
在flask項目中某一個功能中會有多個視圖,那麼from flask import request,current_app,session,g,怎麼保證某次請求的上下文不會被別的視圖拿走呢?
從pycharm中進入globals.py:
_request_ctx_stack = LocalStack()
_app_ctx_stack = LocalStack()
current_app = LocalProxy(_find_app)
request = LocalProxy(partial(_lookup_req_object, 'request'))
session = LocalProxy(partial(_lookup_req_object, 'session'))
g = LocalProxy(partial(_lookup_app_object, 'g'))
線程有個叫做ThreadLocal的類,也就是通常實現線程隔離的類。而werkzeug自己實現了它的線程隔離類:werkzeug.local.Local。LocalStack就是用Local實現的。
而這個LocalProxy 的作用就是可以根據線程/協程返回對應當前協程/線程的對象,也就是說
線程 A 往 LocalProxy 中塞入 A
線程 B 往 LocalProxy 中塞入 B
無論在是什麼地方,
線程 A 永遠取到得是 A,線程 B 取到得永遠是 B
此處引入:
flask中current_app._get_current_object()與current_app有什麼區別
https://segmentfault.com/q/1010000005865632/a-1020000005865704
def __init__(self):
self._local = Local()
def __release_local__(self):
self._local.__release_local__()
def _get__ident_func__(self):
return self._local.__ident_func__
def _set__ident_func__(self, value):
object.__setattr__(self._local, '__ident_func__', value)
__ident_func__ = property(_get__ident_func__, _set__ident_func__)
del _get__ident_func__, _set__ident_func__
def __call__(self):
def _lookup():
rv = self.top
if rv is None:
raise RuntimeError('object unbound')
return rv
return LocalProxy(_lookup)
當 app = Flask(__name__) 構造出一個 Flask App 時,App Context 並不會被自動推入 Stack 中。所以此時 Local Stack 的棧頂是空的,current_app 也是 unbound 狀態。
這就說明了爲什麼上下文需要激活狀態,
那麼爲什麼在應用運行時不需要手動 app_context().push() 呢?
因爲 Flask App 在作爲 WSGI Application 運行時,會在每個請求進入的時候將請求上下文推入。