什么是中间件?中间件的作用,怎么使用中间件及应用场景
什么是中間件?中間件的作用,怎么使用中間件及應(yīng)用場(chǎng)景
如果你想修改請(qǐng)求,例如被傳送到view中的HttpRequest對(duì)象。 或者你想修改view返回的HttpResponse對(duì)象,這些都可以通過(guò)中間件來(lái)實(shí)現(xiàn)。
可能你還想在view執(zhí)行之前做一些操作,這種情況就可以用 middleware來(lái)實(shí)現(xiàn)。
Django默認(rèn)的中間件:(在django項(xiàng)目的settings模塊中,有一個(gè) MIDDLEWARE_CLASSES 變量,其中每一個(gè)元素就是一個(gè)中間件,如下圖)
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',# 'app01.mymid.MyMid1',# 'app01.mymid.MyMid2', ]請(qǐng)求進(jìn)來(lái)是自上而下,通過(guò)反射找到類(lèi),用for循環(huán)來(lái)執(zhí)行,可以自定義中間件,但是也要寫(xiě)在MIDDLEWARE中,可以在app01下創(chuàng)建一個(gè)mymid.py文件來(lái)寫(xiě)我們自定義的中間件
每一個(gè)中間件都有具體的功能
三、自定義中間件
中間件可以定義五個(gè)方法,分別是:(主要的是process_request和process_response)
1、process_request(self,request)2、process_view(self, request, callback, callback_args, callback_kwargs)3、process_template_response(self,request,response)4、process_exception(self, request, exception)5、process_response(self, request, response)以上方法的返回值可以是None或一個(gè)HttpResponse對(duì)象,如果是None,則繼續(xù)按照django定義的規(guī)則向后繼續(xù)執(zhí)行,如果是HttpResponse對(duì)象,則直接將該對(duì)象返回給用戶。
詳細(xì)用法見(jiàn)下方:
1、process_request和process_response
當(dāng)用戶發(fā)起請(qǐng)求的時(shí)候會(huì)依次經(jīng)過(guò)所有的的中間件,這個(gè)時(shí)候的請(qǐng)求時(shí)process_request,最后到達(dá)views的函數(shù)中,views函數(shù)處理后,在依次穿過(guò)中間件,這個(gè)時(shí)候是process_response,最后返回給請(qǐng)求者。
上述截圖中的中間件都是django中的,我們也可以自己定義一個(gè)中間件,我們可以自己寫(xiě)一個(gè)類(lèi),但是必須繼承MiddlewareMixin
第一步:導(dǎo)入
from django.utils.deprecation import MiddlewareMixin第二步:自定義中間件
from django.utils.deprecation import MiddlewareMixin# from django.shortcuts import HttpResponseclass Md1(MiddlewareMixin): def process_request(self,request):print("Md1請(qǐng)求") def process_response(self,request,response):print("Md1返回")return responseclass Md2(MiddlewareMixin):def process_request(self,request):print("Md2請(qǐng)求")#return HttpResponse("Md2中斷")def process_response(self,request,response):#print("Md2返回")return response第三步:在view中定義一個(gè)視圖函數(shù)(index)
def index(request):print("view函數(shù)...")return HttpResponse("OK")第四步:在settings.py的MIDDLEWARE里注冊(cè)自己定義的中間件
運(yùn)行結(jié)果:
Md1請(qǐng)求# Md2請(qǐng)求# view函數(shù)...# Md2返回# Md1返回#**注意:**如果當(dāng)請(qǐng)求到達(dá)請(qǐng)求2的時(shí)候直接不符合條件返回,即return HttpResponse(“Md2中斷”),程序?qū)颜?qǐng)求直接發(fā)給中間件2返回,然后依次返回到請(qǐng)求者,結(jié)果如下:
返回Md2中斷的頁(yè)面,后臺(tái)打印如下:
Md1請(qǐng)求# Md2請(qǐng)求# Md2返回# Md1返回#流程圖如下:
由此總結(jié)一下:
多個(gè)中間件中的process_response方法是按照MIDDLEWARE中的注冊(cè)順序倒序執(zhí)行的,也就是說(shuō)第一個(gè)中間件的process_request方法首先執(zhí)行,而它的process_response方法最后執(zhí)行,最后一個(gè)中間件的process_request方法最后一個(gè)執(zhí)行,它的process_response方法是最先執(zhí)行。
2、process_view
process_view(self, request, view_func, view_args, view_kwargs)
該方法有四個(gè)參數(shù)
request是HttpRequest對(duì)象。
view_func是Django即將使用的視圖函數(shù)。 (它是實(shí)際的函數(shù)對(duì)象,而不是函數(shù)的名稱(chēng)作為字符串。)
view_args是將傳遞給視圖的位置參數(shù)的列表(無(wú)名分組分過(guò)來(lái)的值).
view_kwargs是將傳遞給視圖的關(guān)鍵字參數(shù)的字典(有名分組分過(guò)來(lái)的值)。 view_args和view_kwargs都不包含第一個(gè)視圖參數(shù)(request)。
Django會(huì)在調(diào)用視圖函數(shù)之前調(diào)用process_view方法。
它應(yīng)該返回None或一個(gè)HttpResponse對(duì)象。 如果返回None,Django將繼續(xù)處理這個(gè)請(qǐng)求,執(zhí)行任何其他中間件的process_view方法,然后在執(zhí)行相應(yīng)的視圖。 如果它返回一個(gè)HttpResponse對(duì)象,Django不會(huì)調(diào)用適當(dāng)?shù)囊晥D函數(shù)。 它將執(zhí)行中間件的process_response方法并將應(yīng)用到該HttpResponse并返回結(jié)果。
process_view(self, request, callback, callback_args, callback_kwargs) from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponseclass Md1(MiddlewareMixin):def process_request(self,request):print("Md1請(qǐng)求")#return HttpResponse("Md1中斷")def process_response(self,request,response):print("Md1返回")return responsedef process_view(self, request, callback, callback_args, callback_kwargs):print("Md1view")class Md2(MiddlewareMixin):def process_request(self,request):print("Md2請(qǐng)求")return HttpResponse("Md2中斷")def process_response(self,request,response):print("Md2返回")return responsedef process_view(self, request, callback, callback_args, callback_kwargs):print("Md2view")運(yùn)行結(jié)果:
Md1請(qǐng)求# Md2請(qǐng)求# Md1view# Md2view# view函數(shù)...# Md2返回# Md1返回#下圖進(jìn)行分析上面的過(guò)程:
當(dāng)最后一個(gè)中間的process_request到達(dá)路由關(guān)系映射之后,返回到中間件1的process_view,然后依次往下,到達(dá)views函數(shù),最后通過(guò)process_response依次返回到達(dá)用戶。
process_view可以用來(lái)調(diào)用視圖函數(shù):
class Md1(MiddlewareMixin):def process_request(self,request):print("Md1請(qǐng)求")#return HttpResponse("Md1中斷")def process_response(self,request,response):print("Md1返回")return responsedef process_view(self, request, callback, callback_args, callback_kwargs):# return HttpResponse("hello")response=callback(request,*callback_args,**callback_kwargs)return response運(yùn)行結(jié)果:
Md1請(qǐng)求# Md2請(qǐng)求# view函數(shù)...# Md2返回# Md1返回#注意:process_view如果有返回值,會(huì)越過(guò)其他的process_view以及視圖函數(shù),但是所有的process_response都還會(huì)執(zhí)行。
3、process_exception
process_exception(self, request, exception)
該方法兩個(gè)參數(shù):
一個(gè)HttpRequest對(duì)象
一個(gè)exception是視圖函數(shù)異常產(chǎn)生的Exception對(duì)象。
這個(gè)方法只有在視圖函數(shù)中出現(xiàn)異常了才執(zhí)行,它返回的值可以是一個(gè)None也可以是一個(gè)HttpResponse對(duì)象。如果是HttpResponse對(duì)象,Django將調(diào)用模板和中間件中的process_response方法,并返回給瀏覽器,否則將默認(rèn)處理異常。如果返回一個(gè)None,則交給下一個(gè)中間件的process_exception方法來(lái)處理異常。它的執(zhí)行順序也是按照中間件注冊(cè)順序的倒序執(zhí)行。
process_exception(self, request, exception)實(shí)例如下:
class Md1(MiddlewareMixin):def process_request(self,request):print("Md1請(qǐng)求")#return HttpResponse("Md1中斷")def process_response(self,request,response):print("Md1返回")return responsedef process_view(self, request, callback, callback_args, callback_kwargs):# return HttpResponse("hello")# response=callback(request,*callback_args,**callback_kwargs)# return responseprint("md1 process_view...")def process_exception(self,request,exception):print("md1 process_exception...")class Md2(MiddlewareMixin):def process_request(self,request):print("Md2請(qǐng)求")# return HttpResponse("Md2中斷")def process_response(self,request,response):print("Md2返回")return responsedef process_view(self, request, callback, callback_args, callback_kwargs):print("md2 process_view...")def process_exception(self,request,exception):#只有報(bào)錯(cuò)了才會(huì)執(zhí)行exceptionprint("md1 process_exception...")運(yùn)行結(jié)果:
Md1請(qǐng)求 Md2請(qǐng)求 md1 process_view... md2 process_view... view函數(shù)...Md2返回 Md1返回流程圖如下:
當(dāng)views出現(xiàn)錯(cuò)誤時(shí):
將md2的process_exception修改如下:
def process_exception(self,request,exception):print("md2 process_exception...")return HttpResponse("error")運(yùn)行結(jié)果:
Md1請(qǐng)求# Md2請(qǐng)求# md1 process_view...# md2 process_view...# view函數(shù)...# md2 process_exception...# Md2返回# Md1返回#4、process_template_response(self,request,response)
該方法對(duì)視圖函數(shù)返回值有要求,必須是一個(gè)含有render方法類(lèi)的對(duì)象,才會(huì)執(zhí)行此方法
class Test:def __init__(self,status,msg):self.status=status#self.msg=msg#def render(self):#import json#dic={'status':self.status,'msg':self.msg}#return HttpResponse(json.dumps(dic)) def index(response):#return Test(True,'測(cè)試')四 中間件應(yīng)用場(chǎng)景
1、做IP訪問(wèn)頻率限制
某些IP訪問(wèn)服務(wù)器的頻率過(guò)高,進(jìn)行攔截,比如限制每分鐘不能超過(guò)20次。
2、URL訪問(wèn)過(guò)濾
如果用戶訪問(wèn)的是login視圖(放過(guò))
如果訪問(wèn)其他視圖,需要檢測(cè)是不是有session認(rèn)證,已經(jīng)有了放行,沒(méi)有返回login,這樣就省得在多個(gè)視圖函數(shù)上寫(xiě)裝飾器了!
作為延伸擴(kuò)展內(nèi)容,有余力的同學(xué)可以嘗試著讀一下以下兩個(gè)自帶的中間件:
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',總結(jié)
以上是生活随笔為你收集整理的什么是中间件?中间件的作用,怎么使用中间件及应用场景的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 最好用的临时邮箱网站
- 下一篇: Chap.6 总结《CL: An Int