中間件是Django處理請(qǐng)求和響應(yīng)處理過(guò)程中的一個(gè)鉤子贩挣,它比較輕量級(jí)狡蝶,但是可以用來(lái)改變Django全局的的輸入和輸出佳吞。
每一個(gè)中間件一般都用來(lái)做一些特殊的功能,可以添加多個(gè)中間件來(lái)實(shí)現(xiàn)更多的功能魔眨。
今天一起看一下Django的中間件是如何工作的媳维,如何激活,并且自己寫一個(gè)中間件遏暴。Django還內(nèi)置了一些中間件侄刽,可以拿來(lái)即用。參考內(nèi)置中間件
中間件寫法參考
中間件可以以函數(shù)的形式來(lái)寫朋凉,如下:
def simple_middleware(get_response):
# One-time configuration and initialization.
# 配置和初始化的工作州丹,只執(zhí)行一次
def middleware(request):
# Code to be executed for each request before
# the view (and later middleware) are called.
# 在view被調(diào)用之前,請(qǐng)求還未加工時(shí)執(zhí)行
response = get_response(request)
# Code to be executed for each request/response after
# the view is called.
# 在請(qǐng)求/響應(yīng)處理完畢后調(diào)用的代碼
return response
return middleware
- 函數(shù)必須傳遞的參數(shù)為
get_response
- 返回值必須為
middleware
除了函數(shù)形式為,更多的寫法一般是寫成類的形式墓毒。
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
# 代碼初始化時(shí)候執(zhí)行吓揪,可以做一次性的配置
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
# 在view被調(diào)用之前,請(qǐng)求還未加工時(shí)執(zhí)行
response = self.get_response(request)
# Code to be executed for each request/response after
# the view is called.
# 請(qǐng)求/響應(yīng)被處理之后執(zhí)行
return response
-
__init__
方法只執(zhí)行一次 -
__call__
方法可以執(zhí)行多次
標(biāo)記中間件為不可用狀態(tài)
有時(shí)候所计,你想在項(xiàng)目啟動(dòng)時(shí)判斷是否要用這個(gè)中間件柠辞,這種情況下,在你的init方法中主胧,拋出MiddlewareNotUsed異常叭首。Django就會(huì)移除這個(gè)中間件,如果有日志開啟的話踪栋,DEBUG=True
, 你也可以看到日志輸出的信息焙格。
激活中間件
如果要激活一個(gè)中間件,把它添加到項(xiàng)目settings.py
中的MIDDLEWARE部分夷都。
里面的配置眷唉,每一個(gè)中間件都是以字符串形式來(lái)表示,并且要提供完整的路徑损肛。如下:
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',
'libs.middleware.HandleExceptionMiddleware', # 處理視圖函數(shù)異常
]
建議至少使用一個(gè)中間件厢破,django.middleware.common.CommonMiddleware
中間件的順序也很重要,有時(shí)候某個(gè)中間件需要依賴另外一個(gè)中間件的執(zhí)行結(jié)果才可以生效治拿。例如:
AuthenticationMiddleware
存儲(chǔ)用戶的認(rèn)證信息在Session中摩泪,因此它必須在SessionMiddleware.
中間件之后。
中間件的執(zhí)行順序是從數(shù)組的劫谅,從上往下
執(zhí)行见坑。但是對(duì)于響應(yīng)則是從下往上執(zhí)行。
中間件的其它鉤子
除了基本的請(qǐng)求/響應(yīng)處理的那個(gè)中間件捏检,你還可以添加另外三個(gè)特殊的方法荞驴。
- process_view(request, view_func, view_args, view_kwargs) 在Django調(diào)用view之前執(zhí)行,可以返回None或者HttpResponse對(duì)象贯城。如果返回的是None熊楼,Django會(huì)繼續(xù)執(zhí)行直到找到合適的視圖為止,如果返回的是HttpResponse對(duì)象能犯,Django就停止執(zhí)行鲫骗,然后返回HttpResponse結(jié)果。
process_exception(request, exception) 當(dāng)view拋出異常的時(shí)候踩晶,會(huì)觸發(fā)Django調(diào)用這個(gè)函數(shù)执泰。可以返回None或者HttpResponse對(duì)象渡蜻。同上面
process_template_response(request, response) 當(dāng)view結(jié)束執(zhí)行的時(shí)候調(diào)用术吝,如果響應(yīng)有
render()
方法计济,代表它是個(gè) TemplateResponse。這個(gè)函數(shù)必須要返回一個(gè)響應(yīng)對(duì)象有render()
方法排苍。
最后
中間件還有很多功能沦寂,等待大家一起去發(fā)掘。