Django(part41)--中間鍵Middleware

學習筆記,僅供參考,有錯必究




中間鍵Middleware


中間件是 Django 請求/響應處理的鉤子框架。它是一個輕量級的、低級的插件系統(擁有插件可以增加功能,沒有插件也不影響使用),用於全局改變 Django 的輸入(請求)或輸出(響應)。

每個中間件組件負責做一些特定的功能。例如,中間件組件 AuthenticationMiddleware,它利用會話將用戶與請求關聯起來。


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',
]

中間件類


中間鍵必須繼承自django.utils.deprecation.MiddlewareMixin

中間件類必須實現下列五個方法中的一個或多個:

  • def process_request(self, request)
    • 在每個請求上調用,在執行視圖處理之前被調用,返回None或HttpResponse對象,若返回爲None,則繼續調用視圖處理函數,如果返回爲HttpResponse對象,則不必調用視圖處理函數。
  • def process_view(self, request, callback, callback_args, callback_kwargs)
    • 在每個請求上調用,在執行視圖處理之前被調用,返回None或HttpResponse對象
  • def process_response(self, request, response)
    • 在每個請求上調用,在所有響應返回瀏覽器之前被調用,返回的一定是HttpResponse對象
  • def process_exception(self, request, exception)
    • 當處理過程中拋出異常時調用,返回一個HttpResponse對象
  • def process_template_response(self, request, response)
    • 在每個請求上調用,在視圖剛好執行完畢之後被調用,返回實現了render方法的響應對象

注意, 中間件中的大多數方法在返回None時,表示忽略當前操作進入下一項事件,當返回HttpResponese對象時,表示此請求結束,直接返回給客戶端。


編寫中間鍵


# file : middleware/mymiddleware.py
from django.http import HttpResponse, Http404
from django.utils.deprecation import MiddlewareMixin

class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print("中間件方法 process_request 被調用")
        #在瀏覽器與url管理器之間攔截

    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("中間件方法 process_view 被調用")
        #在url管理器之間與視圖之間攔截

    def process_response(self, request, response):
        print("中間件方法 process_response 被調用")
        return response
    	#視圖到瀏覽器之間

    def process_exception(self, request, exception):
        print("中間件方法 process_exception 被調用")

    def process_template_response(self, request, response):
        print("中間件方法 process_template_response 被調用")
        return response

我們編寫完中間鍵之後,還需要對中間鍵進行註冊(標記中間鍵的位置):

# file : settings.py
MIDDLEWARE = [
    ...
    'middleware.mymiddleware.MyMiddleWare',
]

舉個例子


現在,我們基於以前的Blog製作圖書管理系統裏的項目,我們編寫一箇中間鍵,讓沒有登錄的用戶不能訪問書庫(訪問就報出404),登錄的用戶可以訪問書庫。


我們在項目下新建一個文件夾mymiddleware,專門放中間鍵,在這個文件夾下我們創建一個checklogin.py文件:


現在,我們編寫這個中間鍵:

from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.utils.deprecation import MiddlewareMixin
class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print("中間件MyMiddleWare.process_request方法被調用")
        return None

再對這個中間鍵進行註冊:

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',
    'mymiddleware.checklogin.MyMiddleWare',
]

注意中間鍵的格式爲文件夾名.模塊名.類名


現在,我們開啓服務,並向主頁http://127.0.0.1:8000/發起請求,並查看cmd界面:

June 24, 2020 - 00:13:50
Django version 2.2.13, using settings 'mywebsite_bookstore.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
中間件MyMiddleWare.process_request方法被調用
[24/Jun/2020 00:13:54] "GET / HTTP/1.1" 200 368

可以看到,我們在向主頁/發起請求之前,中間鍵就開始被調用了。

現在,我們更改一下我們的中間鍵:

class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print("中間件MyMiddleWare.process_request方法被調用")
        return HttpResponse("<h2>請求被攔截</h2>")

我們向主頁http://127.0.0.1:8000/發起請求:

再向404測試頁面http://127.0.0.1:8000/test404/發起請求:

可以看到,當我們設置中間鍵返回HttpResponse對象後,我們的請求就無法到達視圖。


現在,我們加一個判斷,如果用戶沒用登錄,就訪問書庫(即調用bookstore應用下的視圖函數),頁面會自動跳轉到登錄頁面(/userinfo/login/);如果登錄了,就可以直接訪問書庫:

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

import re

class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        print("中間件MyMiddleWare.process_request方法被調用")
        if re.match(r'^/bookstore/', request.path_info) \
                and ('userinfo' not in request.session):
            return HttpResponseRedirect('/userinfo/login')
        return None

注意,request.path_info可以拿到請求的路由信息。


現在,我們在未登錄狀態下向主頁http://127.0.0.1:8000/發起請求:

我們點擊查看全部圖書,可以看到頁面跳轉到了登錄頁面:

現在,我們進行登錄,並回到主頁:

點擊查看全部圖書

可以看到,當我們登錄之後,就可以訪問書庫了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章