一 中間件基本介紹
中間件顧名思義,是介于request與response處理之間的一道處理過程,相對比較輕量級,并且在全局上改變django的輸入與輸出。因為改變的是全局,是以需要謹慎實用,用不好會影響到性能。
Django的中間件的定義:
中間件是 Django 用來處理請求和響應的鈎子架構。它是一個輕量級的、底層級的“插件”系統,用于全局性地控制Django 的輸入或輸出,可以了解為内置的app或者小架構。
如果想修改請求,例如被傳送到view中的HttpRequest對象。 或者你想修改view傳回的HttpResponse對象,這些都可以通過中間件來實作。
可能你還想在view執行之前做一些操作,這種情況就可以用 middleware來實作。
Django預設的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',
]
MIDDLEWARE配置項是一個清單,清單中是一個個字元串,這些字元串其實是一個個類,也就是一個個中間件。cnfs也是一個中間件
二 自建一個中間件
2.1 process_request中間件
root@darren-virtual-machine:~/PycharmProjects/cookie_seesion# vim cookie/Middlewares.py
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self,request):
print("MD1下的process_request 方法")
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2下的process_request 方法")
注冊中間件
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',
'cookie.Middlewares.MD1',
'cookie.Middlewares.MD2',
]
通路http://127.0.0.1:8000/cookie/login/,調試結果如下
MD1下的process_request 方法
MD2下的process_request 方法
這裡的結果是按照注冊順序執行的
配置views
from django.shortcuts import render,redirect,HttpResponse
# Create your views here.
def login_required(func):
def inner(request,*args,**kwargs):
if not request.COOKIES.get("is_login"):
return redirect("/cookie/login/")
rep = func(request,*args,**kwargs)
return rep
return inner
@login_required
def index(request):
# if not request.COOKIES.get("is_login"):
# return redirect("/cookie/login/")
print("index 視圖")
return render(request,"index.html")
def login(request):
if request.method == "GET":
return render(request,"login.html")
else:
username = request.POST.get("username")
password = request.POST.get("password")
if username == "joy" and password == "123456":
rep = redirect("/cookie/index/")
rep.set_cookie("is_login",True)
return rep
else:
return redirect("/cookie/login/")
def loginout(request):
rep = redirect("/cookie/login/")
rep.delete_cookie("is_login")
return rep
@login_required
def order(request):
# if not request.COOKIES.get("is_login"):
# return redirect("/cookie/login/")
return HttpResponse("oreder success")
登入檢視結果
MD1下的process_request 方法
MD2下的process_request 方法
index 視圖
process_request是在view之後輸出的
2.2 process_reponse中間件
通路報錯

這是因為在request,必須有回應
輸出結果
MD1下的process_request 方法
MD2下的process_request 方法
MD2下的process_reponse 方法
MD1下的process_reponse 方法
先執行response的MD2
添加響應
結果
MD1下的process_request 方法
MD2下的process_request 方法
index 視圖
MD2下的process_reponse 方法
MD1下的process_reponse 方法
在return response傳回的對象就是
驗證:
views檔案
from django.shortcuts import render,redirect,HttpResponse
# Create your views here.
def login_required(func):
def inner(request,*args,**kwargs):
if not request.COOKIES.get("is_login"):
return redirect("/cookie/login/")
rep = func(request,*args,**kwargs)
return rep
return inner
@login_required
def index(request):
# if not request.COOKIES.get("is_login"):
# return redirect("/cookie/login/")
print("index 視圖")
rep = render(request,"index.html")
print(id(rep))
return rep
def login(request):
if request.method == "GET":
return render(request,"login.html")
else:
username = request.POST.get("username")
password = request.POST.get("password")
if username == "joy" and password == "123456":
rep = redirect("/cookie/index/")
rep.set_cookie("is_login",True)
return rep
else:
return redirect("/cookie/login/")
def loginout(request):
rep = redirect("/cookie/login/")
rep.delete_cookie("is_login")
return rep
@login_required
def order(request):
# if not request.COOKIES.get("is_login"):
# return redirect("/cookie/login/")
return HttpResponse("oreder success")
中間件
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self,request):
print("MD1下的process_request 方法")
def process_response(self,request,response):
print("MD1下的process_reponse 方法")
print(id(response))
return response
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2下的process_request 方法")
def process_response(self,request,response):
print("MD2下的process_reponse 方法")
return response
通路結果,是一緻的
MD1下的process_request 方法
MD2下的process_request 方法
index 視圖
139857132829104
MD2下的process_reponse 方法
MD1下的process_reponse 方法
139857132829104
是以上面錯誤的原因,是因為resonse沒有傳回值,則預設的傳回值為null,導緻報錯,傳回response後,就是傳回render(request,"index.html")
在request添加傳回值
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,redirect,HttpResponse
class MD1(MiddlewareMixin):
def process_request(self,request):
print("MD1下的process_request 方法")
return HttpResponse("Hello 我來了")
def process_response(self,request,response):
print("MD1下的process_response 方法")
print(id(response))
return response
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2下的process_request 方法")
def process_response(self,request,response):
print("MD2下的process_response 方法")
return response
通路http://127.0.0.1:8000/cookie/login/,沒有到view層
輸出
MD1下的process_request 方法
MD1下的process_response 方法
140023033668160
如圖,當reques的中間件中,有傳回值,就會直接傳回,不會走到下面的reques和視圖層,生命請求周期如下:
2.3 process_view方法
該方法有四個參數
- request是HttpRequest對象。
- view_func是Django即将使用的視圖函數。 (它是實際的函數對象,而不是函數的名稱作為字元串。)
- view_args是将傳遞給視圖的位置參數的清單.
- view_kwargs是将傳遞給視圖的關鍵字參數的字典。 view_args和view_kwargs都不包含第一個視圖參數(request)。
Django會在調用視圖函數之前調用process_view方法。
它應該傳回None或一個HttpResponse對象。 如果傳回None,Django将繼續處理這個請求,執行任何其他中間件的process_view方法,然後在執行相應的視圖。 如果它傳回一個HttpResponse對象,Django不會調用适當的視圖函數。 它将執行中間件的process_response方法并将應用到該HttpResponse并傳回結果。
添加process_view
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,redirect,HttpResponse
class MD1(MiddlewareMixin):
def process_request(self,request):
print("MD1下的process_request 方法")
#return HttpResponse("Hello 我來了")
def process_response(self,request,response):
print("MD1下的process_response 方法")
#print(id(response))
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print("MD1下的process_view 方法")
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2下的process_request 方法")
def process_response(self,request,response):
print("MD2下的process_response 方法")
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print("MD2下的process_view 方法")
MD1下的process_request 方法
MD2下的process_request 方法
MD1下的process_view 方法
MD2下的process_view 方法
index 視圖
MD2下的process_response 方法
MD1下的process_response 方法
process_view方法是在process_request之後,視圖函數之前執行的,執行順序按照MIDDLEWARE中的注冊順序從前到後順序執行。
在MD1下的porcess_view傳回一個傳回值
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,redirect,HttpResponse
class MD1(MiddlewareMixin):
def process_request(self,request):
print("MD1下的process_request 方法")
#return HttpResponse("Hello 我來了")
def process_response(self,request,response):
print("MD1下的process_response 方法")
#print(id(response))
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print("MD1下的process_view 方法")
return view_func(request)
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2下的process_request 方法")
def process_response(self,request,response):
print("MD2下的process_response 方法")
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print("MD2下的process_view 方法")
執行結果
MD1下的process_request 方法
MD2下的process_request 方法
MD1下的process_view 方法
index 視圖
MD2下的process_response 方法
MD1下的process_response 方法
2.4 process_exception
文法:
process_exception(self, request, exception)
該方法兩個參數:
- HttpRequest對象
- exception是視圖函數異常産生的Exception對象。
這個方法隻有在視圖函數中出現異常了才執行,它傳回的值可以是一個None也可以是一個HttpResponse對象。如果是HttpResponse對象,Django将調用模闆和中間件中的process_response方法,并傳回給浏覽器,否則将預設處理異常。如果傳回一個None,則交給下一個中間件的process_exception方法來處理異常。它的執行順序也是按照中間件注冊順序的倒序執行。
添加process_exception
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,redirect,HttpResponse
class MD1(MiddlewareMixin):
def process_request(self,request):
print("MD1下的process_request 方法")
#return HttpResponse("Hello 我來了")
def process_response(self,request,response):
print("MD1下的process_response 方法")
#print(id(response))
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print("MD1下的process_view 方法")
#return view_func(request)
def process_exception(self,request,exception):
print("MD1下的process_exception 方法")
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2下的process_request 方法")
def process_response(self,request,response):
print("MD2下的process_response 方法")
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print("MD2下的process_view 方法")
def process_expection(self,request,exception):
print("MD2下的process_exception 方法")
通路結果
MD1下的process_request 方法
MD2下的process_request 方法
MD1下的process_view 方法
MD2下的process_view 方法
index 視圖
MD2下的process_response 方法
MD1下的process_response 方法
并沒有exception,是因為需要view異常才會觸發
制造views異常
from django.shortcuts import render,redirect,HttpResponse
# Create your views here.
def login_required(func):
def inner(request,*args,**kwargs):
if not request.COOKIES.get("is_login"):
return redirect("/cookie/login/")
rep = func(request,*args,**kwargs)
return rep
return inner
@login_required
def index(request):
# if not request.COOKIES.get("is_login"):
# return redirect("/cookie/login/")
print("index 視圖")
int("aaa")
rep = render(request,"index.html")
#print(id(rep))
return rep
def login(request):
if request.method == "GET":
return render(request,"login.html")
else:
username = request.POST.get("username")
password = request.POST.get("password")
if username == "joy" and password == "123456":
rep = redirect("/cookie/index/")
rep.set_cookie("is_login",True)
return rep
else:
return redirect("/cookie/login/")
def loginout(request):
rep = redirect("/cookie/login/")
rep.delete_cookie("is_login")
return rep
@login_required
def order(request):
# if not request.COOKIES.get("is_login"):
# return redirect("/cookie/login/")
return HttpResponse("oreder success")
通路http://127.0.0.1:8000/cookie/index/
輸出結果
MD1下的process_request 方法
MD2下的process_request 方法
MD1下的process_view 方法
MD2下的process_view 方法
index 視圖
MD2下的process_exception 方法
MD1下的process_exception 方法
MD2下的process_response 方法
MD1下的process_response 方法
在exception添加錯誤傳回
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,redirect,HttpResponse
class MD1(MiddlewareMixin):
def process_request(self,request):
print("MD1下的process_request 方法")
#return HttpResponse("Hello 我來了")
def process_response(self,request,response):
print("MD1下的process_response 方法")
#print(id(response))
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print("MD1下的process_view 方法")
#return view_func(request)
def process_exception(self,request,exception):
print("MD1下的process_exception 方法")
return HttpResponse(exception)
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2下的process_request 方法")
def process_response(self,request,response):
print("MD2下的process_response 方法")
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print("MD2下的process_view 方法")
def process_exception(self,request,exception):
print("MD2下的process_exception 方法")
通路結果沒有報錯
MD1下的process_request 方法
MD2下的process_request 方法
MD1下的process_view 方法
MD2下的process_view 方法
index 視圖
MD2下的process_exception 方法
MD1下的process_exception 方法
MD2下的process_response 方法
MD1下的process_response 方法
在MD2傳回
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render,redirect,HttpResponse
class MD1(MiddlewareMixin):
def process_request(self,request):
print("MD1下的process_request 方法")
#return HttpResponse("Hello 我來了")
def process_response(self,request,response):
print("MD1下的process_response 方法")
#print(id(response))
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print("MD1下的process_view 方法")
#return view_func(request)
def process_exception(self,request,exception):
print("MD1下的process_exception 方法")
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2下的process_request 方法")
def process_response(self,request,response):
print("MD2下的process_response 方法")
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print("MD2下的process_view 方法")
def process_exception(self,request,exception):
print("MD2下的process_exception 方法")
return HttpResponse(exception)
MD1下的process_request 方法
MD2下的process_request 方法
MD1下的process_view 方法
MD2下的process_view 方法
index 視圖
MD2下的process_exception 方法
MD2下的process_response 方法
MD1下的process_response 方法
沒有MD1的exception,已經跳過,流程如下
綠色為正常流程,紅色是則MD2添加return傳回
作者:夢中淚
出處:http://www.cnblogs.com/zyxnhr/
關于作者:雲計算,linux,虛拟化,存儲
---------------------------------------------------------------------------
個性簽名:我以為我很頹廢,今天我才知道,原來我早報廢了。
如果覺得本篇文章最您有幫助,歡迎轉載,且在文章頁面明顯位置給出原文連結!記得在右下角點個“推薦”,部落客在此感謝!