這篇文章主要是要和大家簡單介紹 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

