中間件(Middleware)是一個用來處理Django的請求(Request)和響應(Response)的框架級別的鉤子,它是一個輕量、低級別的插件系統,用於在全局範圍內改變Django的輸入和輸出。
當用戶在網站中進行某個操做時,這個過程是用戶向網站發送HTTP請求(Request);而網站會根據用戶的操做發返回相關的網頁內容,這個過程稱爲響應處理(Response)。從請求到響應的過程當中,當Django接收到用戶請求時,首先通過中間件處理請求信息,執行相關的處理,而後將處理結果返回給用戶。
從上圖中可清晰的看到,中間件的做用是處理用戶請求信息和返回響應內容。開發者能夠根據本身的開發需求自定義中間件,只要將自定義的中間件添加到配置屬性MIDDLEWARE中便可激活,通常狀況下,Django默認的中間件配置都可知足大部分開發需求
前端
中間件在settings.py的配置屬性MIDDLEWARE中進行配置,在建立項目是,Django已默認配置了7箇中間件,每一箇中間件的說明以下:django
爲了深刻了解中間件的定義過程,咱們在Pycharm裏打開並查看某個中間件的源碼文件,分析中間件的定義過程,以中間件SessionMiddleware爲例,源碼以下:瀏覽器
class SessionMiddleware(MiddlewareMixin): def __init__(self, get_response=None): self.get_response = get_response engine = import_module(settings.SESSION_ENGINE) self.SessionStore = engine.SessionStore
中間件SessionMiddleware繼承父類MiddlewareMixin,父類MiddlewareMixin只定義函數__init__和__call__,而中間件SessionMiddleware除了重寫父類的__init__以外,還定義了鉤子函數process_request和process_response。
一個完整的中間件設有5個鉤子函數,Django將用戶請求到網站響應的過程進行階段劃分,每一個階段對應執行某個鉤子函數,每一個鉤子函數的運行說明以下。緩存
實戰案例
先來作準備工做,新建一個項目middleware_demo,建立一個子應用middleware_app並在settings.py中註冊,首先配置好路由地址,代碼以下安全
# middleware_demo.urls.py urlpatterns = [ path('middleware/', include('middleware_app.urls')), ] # middleware_app.urls.py urlpatterns = [ path('', views.index, name="index") ]
路由配置完成後,建立視圖函數index,代碼以下:網絡
def index(request): print("中間件首頁") return HttpResponse('中間件首頁')
準備工做作完後,咱們在middleware_app應用中建立middlewares.py文件,填寫以下代碼:session
class FirstMiddleware(MiddlewareMixin): def process_request(self, request): """ 生成請求對象,路由匹配以前 :param request: :return: 若是返回response: 調用當前中間件的process_response處理 若是返回None:調用下一個中間件的process_request處理 """ print("firstMiddleware request") def process_view(self, request, view_func, view_args, view_kwargs): """ 路由匹配完成,視圖函數調用以前 :param request: :param view_func: url路由匹配到的視圖函數 :param view_args: 視圖函數的可變參數 :param view_kwargs: 視圖函數的可變關鍵字參數 :return: 若是返回response:調用最後一箇中間件的process_response開始處理 若是返回None:調用下一個中間件的process_view處理 """ """""" print("firstMiddleware process view") def process_exception(self, request, exception): """ 視圖函數發生異常時 :param request: :param exception: 處理過程當中拋出的異常對象 :return: 若是返回response:以後的process_exception都不會觸發,而是直接調用最後一箇中間件的process_response處理 若是返回None:調用上一個中間件的process_exception處理 """ print("firstMiddleware process exception") def process_response(self, request, response): """ 視圖函數執行後,響應內容返回瀏覽器以前 :param request: :param response: :return: response:調用上一個中間件的process_response處理 """ print("firstMiddleware process response") return response
而後將自定義的中間件插入到settings.py的中間件列表中以下:app
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', 'middleware_app.middlewares.FirstMiddleware', ]
由於中間件是有前後順序的,因此咱們通常自定義的都放在列表最後
框架
接下來咱們訪問路由127.0.0.1/middleware/,查看Pycharm控制檯的日誌輸出ide
firstMiddleware request firstMiddleware process view 中間件首頁 firstMiddleware process response
咱們能夠很清楚的看到請求的執行順序,下面咱們來總結一下
其中,在視圖函數和process_template_response處理過程當中,若是出現 exception ,那麼就會倒序執行中間件的process_exception
總之,你若是有對全局request或response的操做需求,那麼就可使用中間件,例如: