一、什麼是Django中間件
中間件是一個鉤子框架,它們可以介入Django 的請求和響應處理過程。它是一個輕量級、底層的“插件”系統,用於在全局修改Django 的輸入或輸出。每個中間件組件負責完成某個特定的功能。例如:“django.middleware.csrf.CsrfViewMiddleware”中間件的功能是防止POST跨域請求,除非在請求中帶了csrf_token纔會通過。
二、怎樣激活中間件
我們在setting.py文件中配置中間件,在Django1.10之前叫“MIDDLEWARE_CLASSES”,從Django1.10開始就叫“MIDDLEWARE”。
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', ]
三、中間件執行流程
從用戶request到response返回,每一箇中間件中可以定義五種處理函數:
process_request(self,request) process_view(self, request, callback, callback_args, callback_kwargs) process_template_response(self,request,response) process_exception(self, request, exception) process_response(self, request, response)
process_request:
在接到用戶請求時所定義的處理函數。
process_view:
這一步是在路由分發之後,views函數之前所執行的處理函數。
process_template_response:
這個函數基本不用,只有當views函數返回中有render時纔會執行的處理函數。
process_exception:
異常處理函數,只有當views中函數出現異常時纔會執行。其他process_xxx函數出現異常時,是不會觸發此函數的。
process_response:
response返回時執行的處理函數。
一個正常的中間件執行流程:
首先,先從第一個中間件的process_request函數到達最後一箇中間件的process_request函數,如果沒有出現返回的話。緊接着又從第一個中間件的process_view函數一直執行到最後一箇中間件的process_view函數,然後將請求傳遞給views函數處理。views函數返回時,先從最後一箇中間件的process_response開始執行一直到第一個中間件的process_response函數處理完成,然後返回給用戶。
從Django1.10版本開始,當某個中間件的process_request函數觸發了返回,那麼在這個中間件之後的所有中間件方法都不會執行。直接從這個中間件開始向前執行process_response函數,最終返回給用戶。
Django1.10版本之前的版本是,當某個中間件的process_request函數觸發了返回,那麼在這個中間件之後的所有中間件的process_request方法都不會執行,但會從最後一箇中間件開始向前執行process_response函數,最終返回給用戶。
一個包含異常處理的中間件執行流程:
process_exception函數只當views發生異常時纔會執行,它先從最後一箇中間件開始搜索異常處理方法。如果最後一箇中間件沒有處理,它會將異常傳遞給前一箇中間件,如果一直傳遞給第一個中間件都沒有處理異常。它就返回最後一箇中間件開始執行process_response函數,最終返回給用戶。
如果其中某一箇中間件處理了這個異常,它就會立刻返回到最後一箇中間件開始執行process_response函數,在這個中間件之前的所有中間件的process_exception函數就不執行了。
四、如何自定義中間件
a、在項目中新建一個py文件
TestMiddleware.py
b、編輯TestMiddleware.py
from django.utils.deprecation import MiddlewareMixin class TestMiddleware1(MiddlewareMixin): def process_request(self, request): print("Test1-->process_request") def process_response(self, request, response): print("Test1-->process_response") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Test1-->process_view") class TestMiddleware2(MiddlewareMixin): def process_request(self, request): print("Test2-->process_request") def process_response(self, request, response): print("Test2-->process_response") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Test2-->process_view") class TestMiddleware3(MiddlewareMixin): def process_request(self, request): print("Test3-->process_request") def process_response(self, request, response): print("Test3-->process_response") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Test3-->process_view")
在Django1.10之前,我們自定義的中間件類繼承的是Object。從Django1.10開始,我們必須繼承MiddlewareMixin類。
class MiddlewareMixin(object): def __init__(self, get_response=None): self.get_response = get_response super(MiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): response = self.process_request(request) if not response: response = self.get_response(request) if hasattr(self, 'process_response'): response = self.process_response(request, response) return response
c、在setting.py文件添加自定義的中間件
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', 'TestMiddleware.TestMiddleware1', 'TestMiddleware.TestMiddleware2', 'TestMiddleware.TestMiddleware3', ]
MIDDLEWARE是一個列表,所以裏面中間件的順序是很重要的,不能隨意顛倒。爲了不影響它原先的功能,我們把自定義的中間件一般放到最後執行。當然如果你做了一個IP攔截功能的中間件,你也可以把它放到第一個執行。
我們寫了這麼多的process_request、process_view、process_response函數,那這些都是必須要寫的的嗎?答案是否定的,你想寫哪個就寫哪個,自定義中間件中可以寫任意一個或多個函數。這些函數名是不能變的!