這篇文章主要是要和大家簡單介紹 django 中的 middleware 是什麼:notebook:
本篇 django 版本使用 Django==4.2.6
, 如果不知道什麼是 Django, 建議可以閱讀
Django 基本教學 - 從無到有 Django-Beginners-Guide, 教你建立自己的第一個 Django 程式
Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input or output.
簡單說, middleware 的存在就是為了可以更簡單的全局管理(加工) django 的 輸入/輸出, 有點類似裝飾器的概念.
( 如果不知道什麼是裝飾器, 請參考 What is the python decorator )
在 django 中, 你說你從來沒使用過 middleware, 其實是有的, 只是你不知道你有使用過而已:sweat_smile:
在 settings.py 中的 MIDDLEWARE, 就有非常多已經實做好的 middleware:smirk:
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',
]
首先, 先建立 middleware/middleware.py, 以下為片段 code,
...
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
logger.warning('---- One-time configuration and initialization. ----')
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
logger.warning('---- 1 ----')
response = self.get_response(request)
logger.warning('---- 4 ----')
# Code to be executed for each request/response after
# the view is called.
return response
# process_view(), process_exception(), process_template_response()
# special methods to class-based middleware
def process_view(self, request, view_func, view_args, view_kwargs):
# process_view() is called just before Django calls the view.
# It should return either None or an HttpResponse object
logger.warning('---- 2 ----')
return None
def process_exception(self, request, exception):
# Django calls process_exception() when a view raises an exception
# It should return either None or an HttpResponse object
logger.warning('---- exception.args ----')
return None
def process_template_response(self, request, response):
# return TemplateResponse object
logger.warning('---- 3 ----')
return response
__init__
只會執行一次, 就是 django 啟動的時候會載入.
__call__
所謂的 callable.
( 如果不知道什麼是 callable, 請參考 __call__tutorial.py ) youtube - What is the __call__
in python
response = self.get_response(request)
前後代表每個 request 開始與結束會執行的地方.
其中, 裡面的 process_view()
process_exception()
process_template_response()
,
這三個是屬於比較特別的方法,
process_view()
process_view() is called just before Django calls the view.
It should return either None or an HttpResponse object.
process_exception()
Django calls process_exception() when a view raises an exception.
It should return either None or an HttpResponse object.
process_template_response()
process_template_response() is called just after the view has finished executing,
if the response instance has a render() method, indicating that it is a TemplateResponse
or equivalent.
activating middleware, 記得要將 middleware 加入 settings.py 中, 這樣才會生效:+1:
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',
'middleware.middleware.SimpleMiddleware', # <------- activating middleware
]
直接執行 python manage.py runserver
,
瀏覽 http://127.0.0.1:8000/musics/ 觀察 logging.
另外要注意的點是, django 保留了 class django.utils.deprecation.MiddlewareMixin
Django provides django.utils.deprecation.MiddlewareMixin to ease creating middleware classes that are compatible with both MIDDLEWARE and the old MIDDLEWARE_CLASSES. All middleware classes included with Django are compatible with both settings.
以下為官網原文片段,
If used with MIDDLEWARE_CLASSES, the __call__() method will never be used; Django calls process_request() and process_response() directly.
所以說如果你使用了以前的 MIDDLEWARE_CLASSES
, __call__()
method 將會失效.
可參考 Upgrading pre-Django 1.10-style middleware
文章都是我自己研究內化後原創,如果有幫助到您,也想鼓勵我的話,歡迎請我喝一杯咖啡:laughing:
綠界科技ECPAY ( 不需註冊會員 )
歐付寶 ( 需註冊會員 )
MIT license