day62 中间件
一.中間件的介紹
中間件顧名思義,是介于request與response處理之間的一道處理過程,相對(duì)比較輕量級(jí),并且在全局上改變django的輸入與輸出。因?yàn)楦淖兊氖侨?#xff0c;所以需要謹(jǐn)慎實(shí)用,
用不好會(huì)影響到性能
?
1.?Django 的請(qǐng)求生命周期
?
2.Django默認(rèn)自帶的一些中間件
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', ]? 3.執(zhí)行中間件的過程
?
?二. 自定義中間件
1.在項(xiàng)目中創(chuàng)建一個(gè)包
在項(xiàng)目中創(chuàng)建一個(gè)包,隨便起名字,一般都放在一個(gè)叫做utils的包里面,表示一個(gè)公用的組件,創(chuàng)建一個(gè)py文件,隨便起名字,
例如叫做:middlewares.py,內(nèi)容如下
?
from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):#自定義中間件,不是必須要有下面這兩個(gè)方法,有request方法說(shuō)明請(qǐng)求來(lái)了要處理,有response方法說(shuō)明響應(yīng)出去時(shí)需要處理,不是非要寫這兩個(gè)方法,如果你沒寫process_response方法,
那么會(huì)一層一層的往上找,哪個(gè)中間件有process_response方法就將返回對(duì)象給哪個(gè)中間件def process_request(self, request):print("MD1里面的 process_request")def process_response(self, request, response):print("MD1里面的 process_response")return response
?
2.在 settings.py 文件中進(jìn)行注冊(cè)
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','utils.middlewares.MD1', # 自定義中間件MD1,這個(gè)寫的是你項(xiàng)目路徑下的一個(gè)路徑,例如,如果你放在項(xiàng)目下,文件夾名成為utils,
那么這里應(yīng)該寫utils.middlewares.MD1'utils.middlewares.MD2' # 自定義中間件MD2 ]
?
三.常用方法
1. process_request?
process_request有一個(gè)參數(shù),就是request,這個(gè)request和視圖函數(shù)中的request是一樣的。它的返回值可以是None也可以是HttpResponse對(duì)象。返回值是None的話,
按正常流程繼續(xù)走,交給下一個(gè)中間件處理,如果是HttpResponse對(duì)象,
Django將不執(zhí)行視圖函數(shù),而將相應(yīng)對(duì)象返回給瀏覽器。
?
from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):def process_request(self, request):print("MD1里面的 process_request")class MD2(MiddlewareMixin):def process_request(self, request):print("MD2里面的 process_request")pass①在注冊(cè)時(shí) 先注冊(cè) MD1 再注冊(cè) MD2,打印結(jié)果為:
MD1里面的 process_request MD2里面的 process_request app01 中的 index視圖②在注冊(cè)時(shí) 先注冊(cè)MD2 再注冊(cè) MD1,打印結(jié)果為:
MD2里面的 process_request MD1里面的 process_request app01 中的 index視圖 注:多個(gè)中間件中的process_response方法是按照MIDDLEWARE中的注冊(cè)順序倒序執(zhí)行的,
也就是說(shuō)第一個(gè)中間件的process_request方法首先執(zhí)行,而它的process_response
方法最后執(zhí)行,最后一個(gè)中間件的process_request方法最后一個(gè)執(zhí)行,
它的process_response方法是最先執(zhí)行。
?
2. process_response
它有兩個(gè)參數(shù),一個(gè)是request,一個(gè)是response,request就是上述例子中一樣的對(duì)象,response是視圖函數(shù)返回的HttpResponse對(duì)象。該方法的返回值也必須是HttpResponse對(duì)象。
①示例1:
from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):def process_request(self, request):print("MD1里面的 process_request")#不必須寫return值def process_response(self, request, response):#request和response兩個(gè)參數(shù)必須有,名字隨便取print("MD1里面的 process_response")#print(response.__dict__['_container'][0].decode('utf-8')) #查看響應(yīng)體里面的內(nèi)容的方法return response #必須有返回值,寫return response ,這個(gè)response就像一個(gè)接力棒一樣#return HttpResponse('瞎搞') ,如果你寫了這個(gè),那么你視圖返回過來(lái)的內(nèi)容就被它給替代了class MD2(MiddlewareMixin):def process_request(self, request):print("MD2里面的 process_request")passdef process_response(self, request, response): #request和response兩個(gè)參數(shù)必須要有,名字隨便取print("MD2里面的 process_response") return response #必須返回response,不然你上層的中間件就沒有拿到httpresponse對(duì)象,就會(huì)報(bào)錯(cuò)結(jié)果:
MD2里面的 process_request MD1里面的 process_request app01 中的 index視圖 MD1里面的 process_response MD2里面的 process_response 看結(jié)果可知:process_response方法是在視圖函數(shù)之后執(zhí)行的,并且順序是MD1比MD2先執(zhí)行。(此時(shí)settings.py中 MD2比MD1先注冊(cè))多個(gè)中間件中的process_response方法是按照MIDDLEWARE中的注冊(cè)順序倒序執(zhí)行的,
也就是說(shuō)第一個(gè)中間件的process_request方法首先執(zhí)行,而它的process_response方法最后執(zhí)行,
最后一個(gè)中間件的process_request方法最后一個(gè)執(zhí)行,它的process_response方法是最先執(zhí)行。
②示例2:
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponseclass Md1(MiddlewareMixin):def process_request(self,request):print("Md1請(qǐng)求")return HttpResponse("Md2中斷") #process_request方法里面不寫返回值,默認(rèn)也是返回None,如果你自己寫了return None,
也是一樣的效果,不會(huì)中斷你的請(qǐng)求,但是如果你return 的一個(gè)httpresponse對(duì)象,
那么就會(huì)在這個(gè)方法中斷你的請(qǐng)求,直接返回給用戶,這就成了非正常的流程了
#并且,如果你在這里return了httpresponse對(duì)象,那么會(huì)從你這個(gè)中間件類中的
process_response方法開始執(zhí)行返回操作,所以這個(gè)類里面只要有process_response方法,
肯定會(huì)執(zhí)行def process_response(self,request,response):print("Md1返回")return responseclass Md2(MiddlewareMixin):def process_request(self,request):print("Md2請(qǐng)求")
def process_response(self,request,response):print("Md2返回")return response
結(jié)果為:
Md1請(qǐng)求 Md1返回流程圖如下:
?
? 實(shí)例: 訪問白名單設(shè)置
class M1(MiddlewareMixin):def process_request(self,request):#設(shè)置路徑白名單,只要訪問的是login登陸路徑,就不做這個(gè)cookie認(rèn)證if request.path not in [reverse('login'),]:print('我是M1中間件') #客戶端IP地址# return HttpResponse('sorry,沒有通過我的M1中間件')is_login = request.COOKIES.get('is_login', False)if is_login:passelse:# return render(request,'login.html')return redirect(reverse('login'))else:return None #別忘了return Nonedef process_response(self,request,response):print('M1響應(yīng)部分')# print(response.__dict__['_container'][0].decode('utf-8'))return response# return HttpResponse('瞎搞')?
3. 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ù)的名稱作為字符串。)view_args是將傳遞給視圖的位置參數(shù)的列表.view_kwargs是將傳遞給視圖的關(guān)鍵字參數(shù)的字典。
view_args和view_kwargs都不包含第一個(gè)視圖參數(shù)(request)。Django會(huì)在調(diào)用視圖函數(shù)之前,路由匹配之后(process_request方法之后)調(diào)用process_view方法。
?
① 流程圖
?
? ② 示例:(訪問index視圖函數(shù))
from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):def process_request(self, request):print("MD1里面的 process_request")def process_response(self, request, response):print("MD1里面的 process_response")return responsedef process_view(self, request, view_func, view_args, view_kwargs):print("-" * 80)print("MD1 中的process_view")print(view_func, view_func.__name__) #就是url映射到的那個(gè)視圖函數(shù),也就是說(shuō)每個(gè)中間件的這個(gè)process_view已經(jīng)提前拿到了要執(zhí)行的那個(gè)視圖函數(shù)
#ret = view_func(request) #提前執(zhí)行視圖函數(shù),不用到了上圖的試圖函數(shù)的位置再執(zhí)行,
如果你視圖函數(shù)有參數(shù)的話,可以這么寫 view_func(request,view_args,view_kwargs)
#return ret #直接就在MD1中間件這里這個(gè)類的process_response給返回了,
就不會(huì)去找到視圖函數(shù)里面的這個(gè)函數(shù)去執(zhí)行了。class MD2(MiddlewareMixin):def process_request(self, request):print("MD2里面的 process_request")passdef process_response(self, request, response):print("MD2里面的 process_response")return responsedef process_view(self, request, view_func, view_args, view_kwargs):print("-" * 80)print("MD2 中的process_view")print(view_func, view_func.__name__)
結(jié)果:
MD1里面的 process_request MD2里面的 process_request -------------------------------------------------------------------------------- MD1 中的process_view <function index at 0x000001DE68317488> index -------------------------------------------------------------------------------- MD2 中的process_view <function index at 0x000001DE68317488> index app01 中的 index視圖 MD2里面的 process_response MD1里面的 process_response③寫了返回對(duì)象的情況
?
?
返回值是HttpResponse:當(dāng)前中間件之后的中間的process_view方法和視圖函數(shù)都不執(zhí)行,直接執(zhí)行最后一個(gè)中間件的process_reponse方法.?
?
?
4.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í)行。
?
? ①示例1:
from django.utils.deprecation import MiddlewareMixinclass MD1(MiddlewareMixin):def process_request(self, request):print("MD1里面的 process_request")def process_response(self, request, response):print("MD1里面的 process_response")return responsedef process_view(self, request, view_func, view_args, view_kwargs):print("-" * 80)print("MD1 中的process_view")print(view_func, view_func.__name__)def process_exception(self, request, exception):print(exception)print("MD1 中的process_exception")class MD2(MiddlewareMixin):def process_request(self, request):print("MD2里面的 process_request")passdef process_response(self, request, response):print("MD2里面的 process_response")return responsedef process_view(self, request, view_func, view_args, view_kwargs):print("-" * 80)print("MD2 中的process_view")print(view_func, view_func.__name__)def process_exception(self, request, exception):print(exception)print("MD2 中的process_exception")在視圖函數(shù)中拋出一個(gè)異常
def index(request):print("app01 中的 index視圖")raise ValueError("呵呵")return HttpResponse("O98K")流程圖:
?
?
? ②示例2:在process_exception中返回一個(gè)響應(yīng)對(duì)象
class MD2(MiddlewareMixin):def process_request(self, request):print("MD2里面的 process_request")def process_response(self, request, response):print("MD2里面的 process_response")return responsedef process_view(self, request, view_func, view_args, view_kwargs):print("-" * 80)print("MD2 中的process_view")print(view_func, view_func.__name__)def process_exception(self, request, exception):print(exception)print("MD2 中的process_exception")return HttpResponse(str(exception)) # 返回一個(gè)響應(yīng)對(duì)象?
? 結(jié)果:
?
MD1里面的 process_request MD2里面的 process_request -------------------------------------------------------------------------------- MD1 中的process_view <function index at 0x0000022C09727488> index -------------------------------------------------------------------------------- MD2 中的process_view <function index at 0x0000022C09727488> index app01 中的 index視圖 呵呵 MD2 中的process_exception MD2里面的 process_response MD1里面的 process_response流程圖:
?
返回None:正常流程.返回HttpResponse對(duì)象:后面的中間件的process_view方法不執(zhí)行,直接執(zhí)行最后一個(gè)中間件的process_response方法.?
process_template_response(用的比較少)
process_template_response(self, request, response)
它的參數(shù),一個(gè)HttpRequest對(duì)象,response是TemplateResponse對(duì)象(由視圖函數(shù)或者中間件產(chǎn)生)。
process_template_response是在視圖函數(shù)執(zhí)行完成后立即執(zhí)行,但是它有一個(gè)前提條件,那就是視圖函數(shù)返回的對(duì)象有一個(gè)render()方法(或者表明該對(duì)象是一個(gè)TemplateResponse對(duì)象或等價(jià)方法)。
class MD1(MiddlewareMixin):def process_request(self, request):print("MD1里面的 process_request")def process_response(self, request, response):print("MD1里面的 process_response")return responsedef process_view(self, request, view_func, view_args, view_kwargs):print("-" * 80)print("MD1 中的process_view")print(view_func, view_func.__name__)def process_exception(self, request, exception):print(exception)print("MD1 中的process_exception")return HttpResponse(str(exception))def process_template_response(self, request, response):print("MD1 中的process_template_response")return responseclass MD2(MiddlewareMixin):def process_request(self, request):print("MD2里面的 process_request")def process_response(self, request, response):print("MD2里面的 process_response")return responsedef process_view(self, request, view_func, view_args, view_kwargs):print("-" * 80)print("MD2 中的process_view")print(view_func, view_func.__name__)def process_exception(self, request, exception):print(exception)print("MD2 中的process_exception")def process_template_response(self, request, response):print("MD2 中的process_template_response")return responseviews.py中:
def index(request):print("app01 中的 index視圖")def render():print("in index/render")return HttpResponse("O98K")rep = HttpResponse("OK")rep.render = renderreturn rep訪問index視圖,終端輸出的結(jié)果:
MD2里面的 process_request MD1里面的 process_request -------------------------------------------------------------------------------- MD2 中的process_view <function index at 0x000001C111B97488> index -------------------------------------------------------------------------------- MD1 中的process_view <function index at 0x000001C111B97488> index app01 中的 index視圖 MD1 中的process_template_response MD2 中的process_template_response in index/render MD1里面的 process_response MD2里面的 process_response從結(jié)果看出:
視圖函數(shù)執(zhí)行完之后,立即執(zhí)行了中間件的process_template_response方法,順序是倒序,先執(zhí)行MD1的,在執(zhí)行MD2的,接著執(zhí)行了視圖函數(shù)返回的HttpResponse對(duì)象的render方法,返回了一個(gè)新的HttpResponse對(duì)象,接著執(zhí)行中間件的process_response方法。
?
?
?補(bǔ)充:? 登錄時(shí)瀏覽器自動(dòng)加? "/"
①在輸入時(shí)
?
? ②瀏覽器自動(dòng)加 '/'
?
?
? ③在一些情況下不需要加時(shí),
在settings.py文件中進(jìn)行設(shè)置
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/lw1095950124/p/10499985.html
總結(jié)
- 上一篇: VSCode 启动 Vue 项目 npm
- 下一篇: myeclipse中配置spring x