https://docs.djangoproject.com/zh-hans/2.2/topics/http/middleware/
中間件工廠(chǎng)是一個(gè)可調(diào)用的程序斟冕,它接受 get_response 可調(diào)用并返回中間件。中間件是可調(diào)用的缅阳,它接受請(qǐng)求并返回響應(yīng)磕蛇,就像視圖一樣。
中間件可以被寫(xiě)成這樣的函數(shù):
def simple_middleware(get_response):
? ? # One-time configuration and initialization.
? ? def middleware(request):
? ? ? ? # Code to be executed for each request before
? ? ? ? # the view (and later middleware) are called.
? ? ? ? response = get_response(request)
? ? ? ? # Code to be executed for each request/response after
? ? ? ? # the view is called.
? ? ? ? return response
? ? return middleware
或者它可以寫(xiě)成一個(gè)類(lèi)券时,它的實(shí)例是可調(diào)用的孤里,如下:
class SimpleMiddleware:
? ? def __init__(self, get_response):
? ? ? ? self.get_response = get_response
? ? ? ? # One-time configuration and initialization.
? ? def __call__(self, request):
? ? ? ? # Code to be executed for each request before
? ? ? ? # the view (and later middleware) are called.
? ? ? ? response = self.get_response(request)
? ? ? ? # Code to be executed for each request/response after
? ? ? ? # the view is called.
? ? ? ? return response
Django 提供的 get_response 響應(yīng)可能是實(shí)際視圖(如果這是最后列出的中間件)伏伯,或者它可能是鏈中的下一個(gè)中間件橘洞。不需要知道或關(guān)心當(dāng)前的中間件到底是什么,它只是代表了下一步的內(nèi)容说搅。
以上是一個(gè)輕微的簡(jiǎn)化——鏈中最后一個(gè)中間件調(diào)用的 get_response 可不是實(shí)際視圖炸枣,而是處理程序的包裝方法,它負(fù)責(zé)應(yīng)用 view middleware弄唧,調(diào)用具有適當(dāng)URL參數(shù)的視圖适肠,并應(yīng)用 template-response 和 exception 中間件。
中間件可以放在 Python 路徑上的任何地方候引。
__init__(get_response)
中間件工廠(chǎng)必須接受 get_response 參數(shù)侯养。還可以初始化中間件的一些全局狀態(tài)。記住兩個(gè)注意事項(xiàng):
Django僅用 get_response 參數(shù)初始化您的中間件澄干,因此不能定義 __init__() 逛揩,因?yàn)樾枰渌麉?shù)柠傍。
與每次請(qǐng)求調(diào)用 __call__() 方法不同,當(dāng) Web 服務(wù)器啟動(dòng)時(shí)辩稽,__init__() 只被稱(chēng)為*一次*惧笛。
標(biāo)記未使用的中間件
在啟動(dòng)時(shí)確定是否應(yīng)該使用一個(gè)中間件有時(shí)是有用的。在這些情況下逞泄,您的中間件的 __init__() 方法可能會(huì)引發(fā) MiddlewareNotUsed患整。Django 將從中間件進(jìn)程中刪除該中間件,并將調(diào)試消息記錄到 django.request 日志:設(shè)置 DEBUG 為 True喷众。
激活中間件
若要激活中間件組件各谚,請(qǐng)將其添加到 Django 設(shè)置中的 MIDDLEWARE 列表中。
在 MIDDLEWARE 中到千,每個(gè)中間件組件由字符串表示:指向中間件工廠(chǎng)的類(lèi)或函數(shù)名的完整 Python 路徑嘲碧。例如,這里創(chuàng)建的默認(rèn)值是 django-admin startproject:
MIDDLEWARE = [
? ? 'django.middleware.security.SecurityMiddleware',
? ? 'django.contrib.sessions.middleware.SessionMiddleware',
? ? 'django.middleware.common.CommonMiddleware',
? ? 'django.middleware.csrf.CsrfViewMiddleware',
? ? 'django.contrib.auth.middleware.AuthenticationMiddleware',
? ? 'django.contrib.messages.middleware.MessageMiddleware',
? ? 'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Django 安裝不需要任何中間件——如果您愿意的話(huà)父阻,MIDDLEWARE 可以為空——但是強(qiáng)烈建議您至少使用 CommonMiddleware愈涩。
MIDDLEWARE 的順序很重要,因?yàn)橹虚g件會(huì)依賴(lài)其他中間件加矛。例如:類(lèi) AuthenticationMiddleware 在會(huì)話(huà)中存儲(chǔ)經(jīng)過(guò)身份驗(yàn)證的用戶(hù)履婉;因此,它必須在 SessionMiddleware 后面運(yùn)行 斟览。中間件毁腿。Session中間件。請(qǐng)參閱 Middleware ordering 苛茂,用于一些關(guān)于 Django 中間件類(lèi)排序的常見(jiàn)提示已烤。
中間件順序與分層?
在請(qǐng)求階段,在調(diào)用視圖之前妓羊,Django 按照定義的順序應(yīng)用中間件 MIDDLEWARE胯究,自頂向下。
你可以把它想象成一個(gè)洋蔥:每個(gè)中間件類(lèi)都是一個(gè)“層”躁绸,它覆蓋了洋蔥的核心裕循。如果請(qǐng)求通過(guò)洋蔥的所有層(每一個(gè)調(diào)用 get_response )以將請(qǐng)求傳遞到下一層,一直到內(nèi)核的視圖净刮,那么響應(yīng)將在返回的過(guò)程中通過(guò)每個(gè)層(以相反的順序)剥哑。
如果其中一層決定停止并返回響應(yīng)而不調(diào)用get_response,那么該層(包括視圖)中的洋蔥層都不會(huì)看到請(qǐng)求或響應(yīng)淹父。響應(yīng)將只通過(guò)請(qǐng)求傳入的相同層返回株婴。
其他中間件鉤子?
除前面說(shuō)書(shū)的基礎(chǔ)請(qǐng)求/響應(yīng)中間件模式外,你可以給基于類(lèi)的中間件添加三種其他特殊方法:
process_view()?
process_view(request, view_func, view_args, view_kwargs)?
request 是一個(gè) HttpRequest 對(duì)象暑认。view_func 是一個(gè) Django 將要使用的 Python 函數(shù)困介。(這是一個(gè)真實(shí)的函數(shù)對(duì)象揪垄,不是函數(shù)的名稱(chēng));view_args 是一個(gè)用來(lái)傳遞給視圖的位置參數(shù)列表逻翁,饥努;view_kwargs 是一個(gè)用來(lái)傳遞給視圖的關(guān)鍵字參數(shù)字典。view_args 和 view_kwargs 都不包含第一個(gè)視圖參數(shù) ( request )八回。
process_view() 只在 Django 調(diào)用視圖前被調(diào)用酷愧。
它應(yīng)該返回 None 或 HttpResponse 對(duì)象。如果它返回 None 缠诅,Django 將繼續(xù)處理這個(gè)請(qǐng)求溶浴,執(zhí)行任何其他的 process_view() ,然后執(zhí)行相應(yīng)的視圖管引。如果它返回 HttpResponse 對(duì)象士败,Django 不會(huì)去影響調(diào)用相應(yīng)的視圖;它會(huì)將響應(yīng)中間件應(yīng)用到 HttpResponse 并返回結(jié)果褥伴。
注解
在視圖運(yùn)行前或在 process_view() 內(nèi)訪(fǎng)問(wèn)中間件里的 request.POST 將阻止中間件之后運(yùn)行的任何視圖修改請(qǐng)求的上傳處理程序 (modify the upload handlers for the request )谅将,通常應(yīng)該避免這樣。
CsrfViewMiddleware 類(lèi)可以被視為一個(gè)例外重慢,因?yàn)樗峁?csrf_exempt() 和 csrf_protect() 裝飾器饥臂,它們?cè)试S視圖完全控制 CSRF 驗(yàn)證在什么時(shí)候進(jìn)行。