1. 程式人生 > 實用技巧 >django中介軟體及中介軟體實現的登入驗證

django中介軟體及中介軟體實現的登入驗證

django中介軟體及中介軟體實現的登入驗證

1.定義

  一個用來處理Django的請求和響應的框架級別的鉤子(函式),相對比較輕量級,並且在全域性上改變django的輸入與輸出(使用需謹慎,否則影響效能)

  直白的說中介軟體就是幫助我們在檢視函式執行之前和執行之後做一些額外操作

2.用處

  使用者登入

  日誌記錄

  許可權管理

  請求驗證(post)

  一般對所有請求做批量處理的時候用中介軟體,單獨對某幾個函式處理直接使用裝飾器

3.用法說明

  我們使用django一直就在使用中介軟體,開啟django的setting檔案,當中的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(``self``,request)``process_view(``self``, request, view_func, view_args, view_kwargs)``process_template_response(``self``,request,response)``process_exception(``self``, request, exception)``process_response(``self``, request, response)

其中最常用的是process_request和process_response

以上方法的返回值可以是None或一個HttpResponse物件,如果是None,則繼續按照django定義的規則向後繼續執行,如果是HttpResponse物件,則直接將該物件返回給使用者。

3.1 圖例說明

這裡還是先來看看django的生命週期圖例

先從上圖瞭解django執行流程,每一步起了那些關鍵性作用,然後我們再來討論每一箇中間件

3.2 process_request與process_response

  process_request有一個request引數,這個和檢視函式中的request引數一模一樣

  process_response有兩個引數,一個是request,一個是response,request和前面一致,response是檢視函式返回的HttpResponse物件

程式碼例項

  我在應用下建立了一個middlewares檔案,用於存放中介軟體

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

class MD2(MiddlewareMixin):

    def process_request(self, request):
        print('我是MD2的process_request')
  
    def process_response(self, request, response):
        print('我是MD2的process_response')
        return response

setting.py檔案配製新增的中間價位置

訪問一個檢視,終端輸出結果:

總結:

  1.process_request方法,是在檢視函式執行之前執行的,當配製多箇中間件時,會按照MIDDLEWARE中的註冊順序,也就是列表的索引值,從前到後依次執行的

  返回值是None,繼續往後執行,返回值是HttpResponse的物件,執行對應中介軟體的process_response方法

  2.對於檢視函式,是在process_request執行完畢後開始執行的

  3.process_response方法,是在檢視函式之後執行的,而且多箇中間件中的process_response方法是按照MIDDLEWARE中的註冊順序倒序執行的

3.3 process_view

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

該方法有四個引數:

  request是HttpRequest物件。

  view_func是Django即將使用的檢視函式。 (它是實際的函式物件,而不是函式的名稱作為字串。)

  view_args是將傳遞給檢視的位置引數的列表.

  view_kwargs是將傳遞給檢視的關鍵字引數的字典。 view_args和view_kwargs都不包含第一個檢視引數(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')

    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')
        print(view_func, view_func.__name__)class MD2(MiddlewareMixin):
    
    def process_request(self, request):
        print('我是MD2的process_request')
        # return HttpResponse('MD2process_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')
        print(view_func, view_func.__name__)    

效果

總結:

  1.process_view是在檢視執行前執行的,process_request之後,執行順序按照MIDDLEWARE中的註冊順序從前到後順序執行的

3.4 process_exception

  process_exception(self, request, exception)

該方法兩個引數:

  一個HttpRequest物件

  一個exception是檢視函式異常產生的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')

    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')
        print(view_func, view_func.__name__)

    def process_exception(self, request, exception):
        print(exception, '這是MD1的process_exception')
        # return HttpResponse(str(exception))

class MD2(MiddlewareMixin):

    def process_request(self, request):
        print('我是MD2的process_request')
        # return HttpResponse('MD2process_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')
        print(view_func, view_func.__name__)
        # return HttpResponse('這是MD2的process_view')

    def process_exception(self, request, exception):
        print(exception, '這是MD2的process_exception')
        return HttpResponse(str(exception))  # 返回一個響應物件

在檢視函式index中丟擲一個異常

def index(request):
    print('app01中的index檢視')
    raise ValueError("6666")
    return HttpResponse('這是index頁面')

此時結果:

# 可以從結果看出來,exception接收的就是異常資訊,我們的MD1並沒有return HttpResponse(str(exception)) ,但是它卻也丟擲了異常資訊

總結:

  1.只要檢視函式報錯了才執行

  2.在檢視函式之後,process_response之前

3.5 process_template_response(不常用)

  process_template_response是在檢視函式執行完成後立即執行,但是它有一個前提條件,那就是檢視函式返回的物件有一個render()方法

4.中介軟體執行流程

  請求到達中介軟體之後,如果MIDDLEWARE中註冊了6箇中間件,執行過程中,第3箇中間件返回了一個HttpResponse物件,那麼第4,5,6中介軟體的process_request和process_response方法都不執行,順序執行3,2,1中介軟體的process_response方法

process_request方法都執行完後,匹配路由找到要執行的檢視函式,先不執行檢視函式,先執行中介軟體中的process_view方法,process_view方法返回None,繼續按順序執行,所有process_view方法執行完後執行檢視函式。假如中介軟體3 的process_view方法返回了HttpResponse物件,則4,5,6的process_view以及檢視函式都不執行,直接從最後一箇中間件,也就是中介軟體6的process_response方法開始倒序執行。

中介軟體的執行順序:

5.中介軟體實現登入驗證

  以下程式碼還具有阻隔功能,即必須先登入才能訪問主頁,直接從url訪問index會拒絕請求

程式碼例項:

 urls.py

View Code

views.py

View Code

應用app01下的middlewares.py

View Code

settings.py的MIDDLEWARE配置項

View Code

jump.html,用來做中介軟體不通過時,js跳轉

View Code

# 這裡的定製化錯誤資訊效果相當不錯,可以拿來借鑑

login.html

View Code