小白學Django----------中介軟體
中介軟體
定義:是介於request與response處理之間的一道處理過程,相對比較輕量級,並且在全域性上改變django的輸入與輸出。因為改變的是全域性,所以需要謹慎實用,用不好會影響到效能。
1.中介軟體有什麼用
如果你想修改請求,例如被傳送到view中的HttpRequest物件。 或者你想修改view返回的HttpResponse物件,這些都可以通過中介軟體來實現。
可能你還想在view執行之前做一些操作,這種情況就可以用 middleware來實現。
Django預設的中介軟體:
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' ,
]
2.中介軟體的方法
process_request(self,request) #一有返回值,直接就回去了
process_response(self, request, response) #沒有返回值,就會報錯
process_view(self, request, callback, callback_args, callback_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
2.1process_request與process_response
當用戶發起請求時會依次經過所有的中介軟體,這時的請求是process_request,最後到大檢視函式中,檢視 函式處理後,在反向通過中介軟體,這個時候是process_response,最後返回給請求者。
我可以自己定義一箇中間件,要寫一個類,必須繼承MiddlewareMixin
1.匯入
from django.utils.deprecation import MiddlewareMixin
2.自定義中介軟體
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
class Md2(MiddlewareMixin):
def process_request(self,request):
print("Md2請求")
def process_response(self,request,response):
print("Md2返回")
return response
3.在檢視中定義一個函式
def index(request):
print("view函式...")
return HttpResponse("OK")
4.在settings裡的MIDDLEWARE裡註冊自己定義的中介軟體:
Mymiddleware.Md1
Mymiddleware.Md2
結果
Md1請求
Md2請求
view函式...
Md2返回
Md1返回
注意:如果當請求到達請求2的時候直接不符合條件返回,即return HttpResponse(“Md2中斷”),程式將把請求直接發給中介軟體2返回,然後依次返回到請求者,結果如下:
返回Md2中斷的頁面,後臺列印如下:
Md1請求
Md2請求
Md2返回
Md1返回
總結
- 中介軟體的process_request方法是在執行檢視函式之前執行的。
- 當配置多箇中間件時,會按照MIDDLEWARE中的註冊順序,也就是列表的索引值,從前到後依次執行的。
- 不同中介軟體之間傳遞的request都是同一個物件。
多箇中間件中的process_response方法是按照MIDDLEWARE中的註冊順序倒序執行的,也就是說第一個中介軟體的process_request方法首先執行,而它的process_response方法最後執行,最後一箇中間件的process_request方法最後一個執行,它的process_response方法是最先執行。
2.2 process_view
process_view(self, request, view_func, view_args, view_kwargs)
四個引數分別對應:
request:HttpRequest物件。
view_func:Django即將使用的檢視函式。 (它是實際的函式物件,而不是函式的名稱作為字串。)
view_args:無名分組,分出來的引數
view_kwargs:有名分組,分出來的引數
Django會在呼叫檢視函式之前呼叫process_view方法。
它應該返回None或一個HttpResponse物件。 如果返回None,Django將繼續處理這個請求,執行任何其他中介軟體的process_view方法,然後在執行相應的檢視。 如果它返回一個HttpResponse物件,Django不會呼叫適當的檢視函式。 它將執行中介軟體的process_response方法並將應用到該HttpResponse並返回結果。
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
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,view_func,view_args,view_kwargs):
# print('Md1===process_view')
print('Md1===process_view=',view_args)
# 可以做一些操作,但是有返回值時,會跳過Md2的process_view
# obj = view_func(request,view_args,view_kwargs)
# return obj
# view_func:檢視函式
# view_args:無名分組,分出來的引數
# view_kwargs:有名分組,分出來的引數
def process_exception(self,request,exception):
print('Mid1===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,view_func,view_args,view_kwargs):
# print('Md2===process_view')
print('Md2===process_view=',view_args)
結果
Md1請求
Md2請求
Md1view
Md2view
view函式...
Md2返回
Md1返回
注意:process_view如果有返回值,會越過其他的process_view以及檢視函式,但是所有的process_response都還會執行。
2.3 process_exception
process_exception(self, request, exception)
該方法兩個引數:
一個HttpRequest物件
一個exception是檢視函式異常產生的Exception物件。
這個方法只有在檢視函式中出現異常了才執行,它返回的值可以是一個None也可以是一個HttpResponse物件。如果是HttpResponse物件,Django將呼叫模板和中介軟體中的process_response方法,並返回給瀏覽器,否則將預設處理異常。如果返回一個None,則交給下一個中介軟體的process_exception方法來處理異常。它的執行順序也是按照中介軟體註冊順序的倒序執行。
應用方面
可以定義一箇中間件放在MIDDLEWARE列表最上面,當檢視函數出現異常時,通過在process_exception方法中重定向到一個“404此頁面找不到了”的一個頁面顯示給使用者看。
2.4 process_template_response(self,request,response)
該方法對檢視函式返回值有要求,必須是一個含有render方法類的物件,才會執行此方法。
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,'測試')
3.中介軟體的應用場景
3.1 做IP訪問頻率限制
某些IP訪問伺服器的頻率過高,進行攔截,比如限制每分鐘不能超過20次。
3.2 URL訪問過濾
如果使用者訪問的是login檢視(放過)
如果訪問其他檢視,需要檢測是不是有session認證,已經有了放行,沒有返回login,這樣就省得在多個檢視函式上寫裝飾器了!