Django-中介軟體

先生發表於2021-06-27

一、中介軟體簡介

中介軟體就是介於請求和響應處理之間的一道處理過程,相對比較輕量級,並且在全域性上改變Django的輸入與輸出,所以需要謹慎使用。

也就是說中介軟體幫助我們在檢視函式執行之前和執行之後都可以做一些額外的操作,它本質是一個自定義類,類中定義了一些方法,Django框架會在請求的特定時間去執行這些方法。

在Settings.py檔案中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',
]

二、自定義中介軟體

因為中介軟體是我們自己定義的類,所以它主要可以定義四個方法:

這五個方法的返回值可以是None也可以是一個HTTPResponse物件,如果是None,則繼續按照Django定義的規則向後繼續執行,如果是HTTPResponse物件,則直接將改物件返回給使用者

process_request(self,request)	# 主要用的

process_response(self, request, response)	# 主要用的

process_view(self, request, view_func, view_args, view_kwargs)

process_exception(self, request, exception)

示例:

1、在專案中建立一個包,名字自定義,在建立一個py檔案,名字自定義,例如:AuthenMD.py

from django.utils.deprecation import MiddlewareMixin


class MD1(MiddlewareMixin):

    # 請求來了先執行它,在到urls.py
    def process_request(self, request):
        print('MD1的 process_request 操作')

    # 響應的資料要先執行它,在到wsgi.py封裝傳送
    def process_response(self, request, response):
        print('MD1的 process_response 操作')
        return response

2、在Settings.py檔案中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',
    
    # 新增自定義中介軟體配置
    'app01.AuthenMD.MD1',	 # 路徑專案app01/AuthenMD.py檔案中的MD1類
]

三、常用中介軟體方法

在中介軟體中最常用和最主要的方法是process_request和process_response

process_request

process_request(self, request)

process_request有一個引數—>request

request:和檢視函式中的request是一樣的。

它的返回值可以是None亦可以是HTTPResponse物件。

None:按照正常流程繼續走,交給下一個中介軟體處理。

HTTPResponse物件:Django將不執行檢視函式,而將相應的物件返回 給瀏覽器。

from django.utils.deprecation import MiddlewareMixin

class MD1(MiddlewareMixin):

    # 請求來了先執行它,在到urls.py和檢視
    def process_request(self, request):
        print('MD1的 process_request 操作')

注意:

  1. 中介軟體的process_request方法是在執行檢視函式之前執行的。
  2. 當配置多箇中介軟體時,會按照MIDDLEWARF中的註冊順序,也就是列表的索引值,從前到後依次執行。
  3. 不同中介軟體之間傳遞的request都是同一個物件

process_response

process_response(self, request, response)

process_response有兩個引數—>request,response

request:和檢視函式中request一樣。

response:是檢視函式返回的HTTPResponse物件。

該方法的返回值必須是HTTPResponse物件

通常都是返回response

from django.utils.deprecation import MiddlewareMixin

class MD1(MiddlewareMixin):

    # 請求來了先執行它,在到urls.py和檢視
    def process_request(self, request):
        print('MD1的 process_request 操作')
        # 不必寫return,預設返回None

    # 檢視執行後執行它,在到wsgi.py封裝傳送
    def process_response(self, request, response):	# 兩個引數必須有,名字自定義
        print('MD1的 process_response 操作')
        return response		# 必須有返回值,返回response就向接力棒一樣,隨便寫返回內容就會被替代

注意:

  1. process_response方法是在檢視函式之後執行的。
  2. 多箇中介軟體中的process_response方法是按照MIDDLEWARE中的註冊順序倒序執行的。

process_view

process_view(self, request, view_func, view_args, view_kwargs)

process_view有四個引數:

request:是HTTPResponse物件

view_func:是Django即將使用的檢視函式。(實際的函式物件)

view_args:是將傳遞給檢視的位置引數的列表(不包含request)

view_kwargs:是將傳遞給檢視的關鍵字引數的字典。(不包含request)

返回None或者一個HTTPResponse物件

None:Django將繼續處理這個請求,執行其他中介軟體的process_view方法和相應的檢視。

HTTPResponse物件:Django不會呼叫對應的函式,他將直接執行中介軟體中的process_response方法,並將應用到改HTTPResponse並返回結果

from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse


class MD1(MiddlewareMixin):

    def process_request(self, request):
        print('MD1的 process_request 操作')

    def process_response(self, request, response):
        print('MD1的 process_response 操作')
        return response

    # Django會在呼叫檢視函式之前呼叫process_view方法
    def process_view(self, request, view_func, view_args, view_kwargs):
        print('MD1的 process_view 操作')
        
# 輸出
MD1的 process_request 操作
MD1的 process_view 操作
檢視 login 操作
MD1的 process_response 操作

注意:

  1. process_view方法是在process_request方法之後,process_response之前,檢視函式之前執行的。
  2. 執行順序是按照MIDDLEWARE中的註冊順序從前到後順序執行的

process_exception

process_exception(self, request, exception)

改方法有兩個引數:

request:一個HTTPResponse物件

exception:檢視函式異常產生的Exception物件。

返回None或者一個HTTPResponse物件

None:則交給下一個中介軟體的process_exception方法來處理

HTTPResponse物件:Django將呼叫模板和中介軟體中的process_response方法,並返回給瀏覽器,否則預設處理異常。

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_response 操作')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('MD1的 process_view 操作')

    def process_exception(self, request, exception):
        print('MD1的 process_exception 執行了,——>檢視函式出錯了')

        
# 輸出
MD1的 process_request 操作
MD1的 process_view 操作
MD1的 process_exception 執行了,——>檢視函式出錯了
MD1的 process_response 操作

注意:

process_exception方法是在檢視函式出現了錯誤才執行的,否則是不執行的。

四、中介軟體版登入認證

views.py檔案

from django.shortcuts import render, redirect


def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        name = request.POST.get('uname')
        pwd = request.POST.get('pwd')
        if name == 'xiaoyang' and pwd == '123':
            request.session['is_login'] = 'True'
            return redirect('index')
        else:
            return redirect('login')


def index(request):
    return render(request, 'index.html')


def quit(request):
    request.session.flush()     # 刪除sessionid,服務端和瀏覽器都刪除
    return render(request, 'login.html')

AuthenDM.py 中介軟體檔案

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect

# 白名單,白名單中的不需要驗證session
WHITE_LIST = [
    '/login/'
]

class MD1(MiddlewareMixin):

    def process_request(self, request):	
        if request.path in WHITE_LIST:  # 地址在白名單中就放行
            return
        else:
            # 不在白名單中就判斷session
            is_login = request.session.get('is_login')
            if is_login == 'True':      # 登入了就放行
                return
            else:                       # 沒登入就直接跳轉到登入頁面
                return redirect('login')

相關文章