1. 程式人生 > >小白學Django----------中介軟體

小白學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,這樣就省得在多個檢視函式上寫裝飾器了!