django中介軟體
中介軟體是 Django 用來處理請求和響應的鉤子框架。它是一個輕量級的、底層級的“外掛”系統,用於全域性性地控制Django 的輸入或輸出,可以理解為一些關卡。
中介軟體可以放在你的工程的任何地方,並以Python路徑的方式進行訪問。
可以把中介軟體比喻成洋蔥,每一層代表一箇中介軟體,每個請求從進入django到響應返回,django都可以通過中介軟體進行一定的操作。
啟用中介軟體
在settings.py中,MIDDLEWARE列表表示要啟用的中介軟體。
MIDDLEWARE = [
# 安全中介軟體
'django.middleware.security.SecurityMiddleware',
# 會話中介軟體,啟用時支援session
'django.contrib.sessions.middleware.SessionMiddleware',
# “通用”中介軟體
'django.middleware.common.CommonMiddleware',
# CSRF 保護中介軟體
'django.middleware.csrf.CsrfViewMiddleware',
# 驗證中介軟體
'django.contrib.auth.middleware.AuthenticationMiddleware',
# 訊息中介軟體
'django.contrib.messages.middleware.MessageMiddleware',
# X-Frame-Options 中介軟體
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
上面的是預設的配置,關於這些中介軟體的功能,可以點選這裡檢視。
自定義中介軟體
自定義中介軟體有兩種方法,一種是比較老的方法,另一種是在老方法的基礎上的新的定義方式。
- 老方式
要點:
- 自定義一個
from django.utils.deprecation.MiddlewareMixin
的子類 - 為類寫鉤子函式(鉤子函式如下表)
鉤子函式 | 執行時機 | 執行順序(相對與配置列表) | 引數 | 返回值 |
---|---|---|---|---|
process_request | 請求剛到來,執行檢視之前 | 正序 | HttpRequest物件 | None或者HttpResponse物件 |
process_response | 檢視執行完畢,返回響應時 | 逆序 | HttpRequest物件和HttpResponse物件 | HttpResponse物件 |
process_view | process_request之後,路由轉發到檢視,執行檢視之前 | 正序 | HttpRequest物件, 檢視函式, view args引數, view kwargs引數 | None或者HttpResponse物件 |
process_exception | 檢視執行中發生異常時 | 逆序 | HttpRequest物件和異常類物件 | None或者HttpResponse物件 |
process_template_response | 檢視剛執行完畢,process_response之前 | 逆序 | HttpRequest物件和TemplateResponse物件 | 實現了render方法的響應物件 |
例子:
# app01/middlewares/miMiddleware.py
from django.utils.deprecation import MiddlewareMixin
class MyMiddleWare(MiddlewareMixin):
def process_request(self, request):
print("處理請求")
def process_response(self, request, response):
print("返回響應")
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print("在執行%s檢視前" % view_func.__name__)
def process_exception(self, request, exception):
print("處理檢視異常...")
# settings.py
MIDDLEWARE = [
"app01.middlewares.myMiddleware.MyMiddleWare",
]
- 新方式
不需要繼承MiddlewareMixin
類,而且process_request
和process_response
定義__call__方法中。
class MyMiddleWare:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
print("處理請求")
response = self.get_response(request)
print("返回響應")
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print("在執行%s檢視前" %view_func.__name__)
def process_exception(self,request,exception):
print("處理檢視異常...")
同樣需要在settings配置MIDDLEWARE。
應用例項一:IP攔截
如果我們想限制某些IP對伺服器的訪問,可以在settings.py
中新增一個BLACKLIST
(全大寫)列表,將被限制的IP地址寫入其中。
然後,我們就可以編寫下面的中介軟體了:
from django.http import HttpResponseForbidden
from django.conf import settings
class BlackListMiddleware():
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.META['REMOTE_ADDR'] in getattr(settings, "BLACKLIST", []):
return HttpResponseForbidden('<h1>該IP地址被限制訪問!</h1>')
response = self.get_response(request)
return response
應用例項二:DEBUG頁面
網站上線正式執行後,我們會將DEBUG改為 False,這樣更安全。但是發生伺服器5xx系列錯誤時,管理員卻不能看到錯誤詳情,除錯很不方便。有沒有辦法比較方便地解決這個問題呢?
即:
- 普通訪問者看到的是500錯誤頁面
- 管理員看到的是錯誤詳情Debug頁面
利用中介軟體就可以做到!程式碼如下:
import sys
from django.views.debug import technical_500_response
from django.conf import settings
class DebugMiddleware():
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_exception(self, request, exception):
# 如果是管理員,則返回一個特殊的響應物件,也就是Debug頁面
# 如果是普通使用者,則返回None,交給預設的流程處理
if request.user.is_superuser or request.META.get('REMOTE_ADDR') in settings.ADMIN_IP:
return technical_500_response(request, *sys.exc_info())