Django請求執行流程圖: 中間件 中間件的概念 中間件顧名思義,是介於request與response處理之間的一道處理過程,相對比較輕量級,並且在全局上改變django的輸入與輸出。因為改變的是全局,所以需要謹慎使用,用不好會影響到性能。 Django的中間件官方定義: 如果你想修改請求,例如 ...
Django請求執行流程圖:
中間件
中間件的概念
中間件顧名思義,是介於request與response處理之間的一道處理過程,相對比較輕量級,並且在全局上改變django的輸入與輸出。因為改變的是全局,所以需要謹慎使用,用不好會影響到性能。
Django的中間件官方定義:
Middleware is a framework of hooks into Django’s request/response processing. <br>It’s a light, low-level “plugin” system for globally altering Django’s input or output.
如果你想修改請求,例如被傳送到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', ]
其中每一個中間件都有具體的功能
自定義中間件
中間件中一共有四個方法:
process_request
process_response
process_view
process_exception
process_request,process_response
當用戶發起請求的時候會依次經過所有的的中間件,這個時候的請求是process_request,最後到達views的函數中,views函數處理後,在依次穿過中間件,這個時候是process_response,最後返回給請求者。
上述圖片的中間件都是django預設的,我們也可以自己定義一個中間件,我們可以自己寫一個類,但是必須繼承MiddlewareMixin
首先,在app01下創建utils包,在包下麵創建middlewares.py文件(這個文件中是存放自定義中間件所對應的類的)
middlewares.py中:
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class Md1(MiddlewareMixin): def process_request(self,request): print("Md1請求") #return HttpResponse("禁止") def process_response(self,request,response): print("Md1返回") return response class Md2(MiddlewareMixin): def process_request(self,request): print("Md2請求") def process_response(self,request,response): print("Md2返回") return response
在settings中添加中間件Md1和Md2:
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.utils.midddlewares.Md1', 'app01.utils.midddlewares.Md2', ]
關於中間件Md1和Md2的位置,從啟動文件開始,app01和啟動文件在同一目錄下,所以就是app01.utils.midddlewares.Md1
urls.py中:
from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('index/', views.index), ]
views.py中:
def index(request): print("view函數...") return HttpResponse("OK")
執行結果:
Md1請求
Md2請求
view函數...
Md2返回
Md1返回
執行流程說明:用戶發起請求,執行Md1中的process_request,列印"Md1請求";接著執行Md2中的process_request,列印"Md2請求";再通過url路由分發的index找到index視圖函數,列印"view函數...",返迴響應對象"OK"(將來要顯示在頁面上的內容);接著執行Md2中的process_response,列印"Md2返回";繼續執行Md1中的process_response,列印"Md1返回",最後將響應內容呈現給用戶。
註意:如果在請求到達Md1中的process_request時,直接不符合條件返回,即return HttpResponse("禁止"),程式將把請求直接發給Md1的process_response返回,然後依次返回到請求者,結果如下:
頁面中顯示"禁止",列印內容如下:
Md1請求
Md2請求
流程圖如下:
process_view:
process_view(self, request, callback, callback_args, callback_kwargs)
middlewares.py文件中:
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class Md1(MiddlewareMixin): def process_request(self,request): print("Md1請求") def process_response(self,request,response): print("Md1返回") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Md1view") class Md2(MiddlewareMixin): def process_request(self,request): print("Md2請求") return HttpResponse("Md2中斷") def process_response(self,request,response): print("Md2返回") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Md2view")
執行結果如下:
Md1請求
Md2請求
Md1view
Md2view
view函數...
Md2返回
Md1返回
分析過程圖如下:
url請求進來之後,一定會執行中間件1和中間件2的process_request函數,路由分發是在這兩個請求執行完之後的,當最後一個中間件的process_request到達路由關係映射之後,返回到中間件1的process_view,然後依次往下,到達views函數,最後通過process_response依次返回到達用戶。
既然process_view是在路由控制之後,那麼在process_view這一層就可以調用視圖函數了。
class Md1(MiddlewareMixin): def process_request(self,request): print("Md1請求") #return HttpResponse("Md1中斷") def process_response(self,request,response): print("Md1返回") return response def process_view(self, request, callback, callback_args, callback_kwargs): # return HttpResponse("hello") response=callback(request,*callback_args,**callback_kwargs) return response
執行結果如下:
Md1請求
Md2請求
view函數...
Md2返回
Md1返回
註意:process_view如果有返回值,會越過其他的process_view以及視圖函數,但是所有的process_response都還會執行。
process_exception:
process_exception(self, request, exception)
示例修改如下:
class Md1(MiddlewareMixin): def process_request(self,request): print("Md1請求") #return HttpResponse("Md1中斷") def process_response(self,request,response): print("Md1返回") return response def process_view(self, request, callback, callback_args, callback_kwargs): # return HttpResponse("hello") # response=callback(request,*callback_args,**callback_kwargs) # return response print("md1 process_view...") def process_exception(self, request, response): print("md1 process_exception...") class Md2(MiddlewareMixin): def process_request(self,request): print("Md2請求") # return HttpResponse("Md2中斷") def process_response(self,request,response): print("Md2返回") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("md2 process_view...") def process_exception(self, request, response): print("md2 process_exception...")
視圖函數沒有出錯時:
Md1請求
Md2請求
md1 process_view...
md2 process_view...
view函數...
Md2返回
Md1返回
當views.py出錯時,流程圖如下:
當視圖函數出錯時:
Md1請求
Md2請求
md1 process_view...
md2 process_view...
view函數...
md2 process_exception...
md1 process_exception...
Md2返回
Md1返回
應用案例
1、做IP訪問頻率限制
某些IP訪問伺服器的頻率過高,進行攔截,比如限制每分鐘不能超過20次。
2、URL訪問過濾
如果用戶訪問的是login視圖(放過)
如果訪問其他視圖,需要檢測是不是有session認證,已經有了放行,沒有返回login,這樣就省得在多個視圖函數上寫裝飾器了!
作者:流浪者
日期:2019-10-03