Django 編寫(xiě)自己的中間件

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)行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末似踱,一起剝皮案震驚了整個(gè)濱河市隅熙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌核芽,老刑警劉巖囚戚,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異轧简,居然都是意外死亡驰坊,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)吉懊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)庐橙,“玉大人,你說(shuō)我怎么就攤上這事借嗽。” “怎么了转培?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵恶导,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我浸须,道長(zhǎng)惨寿,這世上最難降的妖魔是什么邦泄? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮裂垦,結(jié)果婚禮上顺囊,老公的妹妹穿的比我還像新娘。我一直安慰自己蕉拢,他們只是感情好特碳,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著晕换,像睡著了一般午乓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上闸准,一...
    開(kāi)封第一講書(shū)人閱讀 52,736評(píng)論 1 312
  • 那天益愈,我揣著相機(jī)與錄音,去河邊找鬼夷家。 笑死蒸其,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的库快。 我是一名探鬼主播枣接,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼缺谴!你這毒婦竟也來(lái)了但惶?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤湿蛔,失蹤者是張志新(化名)和其女友劉穎膀曾,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體阳啥,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡添谊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了察迟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斩狱。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖扎瓶,靈堂內(nèi)的尸體忽然破棺而出所踊,到底是詐尸還是另有隱情,我是刑警寧澤概荷,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布秕岛,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏继薛。R本人自食惡果不足惜修壕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望遏考。 院中可真熱鬧慈鸠,春花似錦、人聲如沸灌具。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)稽亏。三九已至壶冒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間截歉,已是汗流浹背胖腾。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瘪松,地道東北人咸作。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像宵睦,于是被迫代替她去往敵國(guó)和親记罚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容