學習筆記,僅供參考,有錯必究
中間鍵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/發起請求:
我們點擊查看全部圖書
,可以看到頁面跳轉到了登錄頁面:
現在,我們進行登錄,並回到主頁:
點擊查看全部圖書
:
可以看到,當我們登錄之後,就可以訪問書庫了。