<!--
譯者:Github@wizardforcel
-->
# 中間件 #
中間件是一個介入Django的請求和響應的處理過程中的鉤子框架。它是一個輕量級,底層的“插件”系統,用于在全局修改Django的輸入或輸出。
中間件組件責任處理某些特殊的功能。例如,Django包含一個中間件組件,AuthenticationMiddleware ,使用會話將用戶和請求關聯。
這篇文檔講解了中間件如何工作,如何激活中間件,以及如何編寫自己的中間件。Django集成了一些內置的中間件可以直接開箱即用。它們被歸檔在 內置中間件參考.
## 激活中間件 ##
要激活一個中間件組件,需要把它添加到你Django配置文件中的MIDDLEWARE_CLASSES 列表中。
在MIDDLEWARE_CLASSES中,每一個中間件組件用字符串的方式描述:一個完整的Python全路徑加上中間件的類名稱。例如,使用 django-admin startproject創建工程的時候生成的默認值:
```
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
)
```
Django的程序中,中間件不是必需的 — 只要你喜歡,MIDDLEWARE_CLASSES可以為空 — 但是強烈推薦你至少使用CommonMiddleware。
MIDDLEWARE_CLASSES中的順序非常重要,因為一個中間件可能依賴于另外一個。例如,AuthenticationMiddleware在會話中儲存已認證的用戶。所以它必須在SessionMiddleware之后運行。一些關于Django中間件類的順序的常見提示,請見Middleware ordering。
## 鉤子和應用順序 ##
在請求階段中,調用視圖之前,Django會按照MIDDLEWARE_CLASSES中定義的順序自頂向下應用中間件。會用到兩個鉤子:
+ process_request()
+ process_view()
在響應階段中,調用視圖之后,中間件會按照相反的順序應用,自底向上。會用到三個鉤子:
+ process_exception() (僅當視圖拋出異常的時候)
+ process_template_response() (僅用于模板響應)
+ process_response()

如果你愿意的話,你可以把它想象成一顆洋蔥:每個中間件都是包裹視圖的一層“皮”。
每個鉤子的行為接下來會描述。
## 編寫自己的中間件 ##
編寫自己的中間件很容易的。每個中間件組件是一個單獨的Python的class,你可以定一個或多個下面的這些方法:
### process_request ###
**process_request(request)**
request是一個HttpRequest 對象。
在Django決定執行哪個視圖(view)之前,process_request()會被每次請求調用。
它應該返回一個None 或一個HttpResponse對象。如果返回 None, Django會繼續處理這個請求,執行其他process_request()中間件,然后process_view()中間件顯示對應的視圖。如果它返回一個HttpResponse對象,Django便不再會去調用其他的請求(request), 視圖(view)或其他中間件,或對應的視圖;處理HttpResponse的中間件會處理任何返回的響應(response)。
### process_view ###
**process_view(request, view_func, view_args, view_kwargs)**
request是一個HttpRequest對象。view_func是 Django會調用的一個Python的函數。(它確實是一個函數對象,不是函數的字符名稱。) view_args是一個會被傳遞到視圖的位置參數列表,而view_kwargs 是一個會被傳遞到視圖的關鍵字參數字典。 view_args和 view_kwargs 都不包括第一個視圖參數(request)。
process_view()會在Django調用視圖(view)之前被調用。
它將返回None 或一個HttpResponse 對象。如果返回 None,將會繼續處理這個請求,執行其他的process_view() 中間件,然后顯示對應的視圖。如果返回HttpResponse對象,Django就不再會去調用其他的視圖(view),異常中間件(exception middleware)或對應的視圖 ;它會把響應中間件應用到HttpResponse上,并返回結果。
> 注意
>
> 在中間件內部,從process_request或者process_view方法中訪問request.POST或者request.REQUEST將會阻礙該中間 件之后的所有視圖無法修改request的上傳處理程序, 一般情況要避免這樣使用。
> 類CsrfViewMiddleware可以被認為是個例外 ,因為它提供了csrf_exempt() 和 csrf_protect()兩個允許視圖來精確控制 在哪個點需要開啟CSRF驗證。
### process_template_response ###
**process_template_response(request, response)**
request是一個HttpRequest對象。response是一個TemplateResponse對象(或等價的對象),由Django視圖或者中間件返回。
如果響應的實例有render()方法,process_template_response()在視圖剛好執行完畢之后被調用,這表明了它是一個TemplateResponse對象(或等價的對象)。
這個方法必須返回一個實現了render方法的響應對象。它可以修改給定的response對象,通過修改 response.template_name和response.context_data或者它可以創建一個全新的 TemplateResponse或等價的對象。
你不需要顯式渲染響應 —— 一旦所有的模板響應中間件被調用,響應會自動被渲染。
在一個響應的處理期間,中間件以相反的順序運行,這包括process_template_response()。
### process_response ###
**process_response(request, response)**
request是一個HttpRequest對象。response是Django視圖或者中間件返回的HttpResponse或者StreamingHttpResponse對象。
process_response()在所有響應返回瀏覽器之前被調用。
這個方法必須返回HttpResponse或者StreamingHttpResponse對象。它可以改變已有的response,或者創建并返回新的HttpResponse或StreamingHttpResponse對象。
不像 process_request()和process_view()方法,即使同一個中間件類中的process_request()和process_view()方法會因為前面的一個中間件返回HttpResponse而被跳過,process_response()方法總是會被調用。特別是,這意味著你的process_response()方法不能依賴于process_request()方法中的設置。
最后,記住在響應階段中,中間件以相反的順序被應用,自底向上。意思是定義在MIDDLEWARE_CLASSES最底下的類會最先被運行。
### 處理流式響應 ###
不像HttpResponse,StreamingHttpResponse并沒有content屬性。所以,中間件再也不能假設所有響應都帶有content屬性。如果它們需要訪問內容,他們必須測試是否為流式響應,并相應地調整自己的行為。
```
if response.streaming:
response.streaming_content = wrap_streaming_content(response.streaming_content)
else:
response.content = alter_content(response.content)
```
> 注意
>
> 我們需要假設streaming_content可能會大到在內存中無法容納。響應中間件可能會把它封裝在新的生成器中,但是一定不要銷毀它。封裝一般會實現成這樣:
>
```
def wrap_streaming_content(content):
for chunk in content:
yield alter_content(chunk)
```
>
### process_exception ###
**process_exception(request, exception)**
request是一個HttpRequest對象。exception是一個被視圖中的方法拋出來的 Exception對象。
當一個視圖拋出異常時,Django會調用process_exception()來處理。process_exception()應該返回一個None 或者一個HttpResponse對象。如果它返回一個HttpResponse對象,模型響應和響應中間件會被應用,響應結果會返回給瀏覽器。Otherwise, default exception handling kicks in.
再次提醒,在處理響應期間,中間件的執行順序是倒序執行的,這包括process_exception。如果一個異常處理的中間件返回了一個響應,那這個中間件上面的中間件都將不會被調用。
### \_\_init\_\_ ###
大多數的中間件類都不需要一個初始化方法,因為中間件的類定義僅僅是為process\_\*提供一個占位符。如果你確實需要一個全局的狀態那就可以通過\_\_init\_\_來加載。然后要銘記如下兩個警告:
Django初始化你的中間件無需任何參數,因此不要定義一個有參數的\_\_init\_\_方法。
不像process\_\*每次請求到達都要調用\_\_init\_\_只會被調用一次,就是在Web服務啟動的時候。
### 標記中間件不被使用 ###
有時在運行時決定是否一個中間件需要被加載是很有用的。 在這種情況下,你的中間件中的 \_\_init\_\_方法可以拋出一個django.core.exceptions.MiddlewareNotUsed異常。Django會從中間件處理過程中移除這部分中間件,并且當DEBUG為True的時候在django.request記錄器中記錄調試信息。
```
1.8中的修改:
之前 MiddlewareNotUsed異常不會被記錄。
```
## 指導準則 ##
+ 中間件的類不能是任何類的子類。
+ 中間件可以存在與你Python路徑中的任何位置。 Django所關心的只是被包含在MIDDLEWARE_CLASSES中的配置。
+ 將Django’s available middleware作為例子隨便看看。
+ 如果你認為你寫的中間件組建可能會對其他人有用,那就把它共享到社區! 讓我們知道它,我們會考慮把它添加到Django中。
- 新手入門
- 從零開始
- 概覽
- 安裝
- 教程
- 第1部分:模型
- 第2部分:管理站點
- 第3部分:視圖和模板
- 第4部分:表單和通用視圖
- 第5部分:測試
- 第6部分:靜態文件
- 高級教程
- 如何編寫可重用的應用
- 為Django編寫首個補丁
- 模型層
- 模型
- 模型語法
- 元選項
- 模型類
- 查詢集
- 執行查詢
- 查找表達式
- 模型的實例
- 實例方法
- 訪問關聯對象
- 遷移
- 模式編輯器
- 編寫遷移
- 高級
- 管理器
- 原始的SQL查詢
- 聚合
- 多數據庫
- 自定義查找
- 條件表達式
- 數據庫函數
- 其它
- 遺留的數據庫
- 提供初始數據
- 優化數據庫訪問
- 視圖層
- 基礎
- URL配置
- 視圖函數
- 快捷函數
- 裝飾器
- 參考
- 內建的視圖
- TemplateResponse 對象
- 文件上傳
- 概覽
- File 對象
- 儲存API
- 管理文件
- 自定義存儲
- 基于類的視圖
- 概覽
- 內建顯示視圖
- 內建編輯視圖
- API參考
- 分類索引
- 高級
- 生成 CSV
- 生成 PDF
- 中間件
- 概覽
- 內建的中間件類
- 模板層
- 基礎
- 面向設計師
- 語言概覽
- 人性化
- 面向程序員
- 表單
- 基礎
- 概覽
- 表單API
- 內建的Widget
- 高級
- 整合媒體
- 開發過程
- 設置
- 概覽
- 應用程序
- 異常
- 概覽
- django-admin 和 manage.py
- 添加自定義的命令
- 測試
- 介紹
- 部署
- 概述
- WSGI服務器
- 部署靜態文件
- 通過email追蹤代碼錯誤
- Admin
- 管理操作
- 管理文檔生成器
- 安全
- 安全概述
- 說明Django中的安全問題
- 點擊劫持保護
- 加密簽名
- 國際化和本地化
- 概述
- 本地化WEB UI格式化輸入
- “本地特色”
- 常見的網站應用工具
- 認證
- 概覽
- 使用認證系統
- 密碼管理
- 日志
- 分頁
- 會話
- 數據驗證
- 其它核心功能
- 按需內容處理
- 重定向
- 信號
- 系統檢查框架