为什么中间件 mixin 在 django.utils.deprecation.py 中声明

Why middleware mixin declared in django.utils.deprecation.py

在路径 django.utils.deprecation.py 中,我们有一些 class 关于方法的弃用警告。

在该文件中我们有一个名为 MiddlewareMixin 的 class。这个 class 用于编写中间件 classes。虽然与弃用无关,但为什么这个 class 写在这个路径中?

简而言之:它是一个将弃用中间件变成新中间件的工具,尽管它有一些限制。

Django 的中间件 "style" 已经改变。这个 MiddlewareMixin 在大多数情况下可以 "convert" 一个老式的中间件 class 到一个新式的中间件 decorator,正如 [=28] 中所写=]:

class django.utils.deprecation.MiddlewareMixin

(...)

In most cases, inheriting from this mixin will be sufficient to make an old-style middleware compatible with the new system with sufficient backwards-compatibility. The new short-circuiting semantics will be harmless or even beneficial to the existing middleware. In a few cases, a middleware class may need some changes to adjust to the new semantics.

在"old days"(在之前),中间件是这样写的:

class SomeMiddleware:

    def process_request(self, request):
        # ...
        pass

    def process_response(self, request, response):
        # ...
        return response

但是如今,中间件更多地被视为 "underlying middleware" 周围的某种 "decorator",最终是视图。如 documentation on the new middleware 中指定:

A middleware can be written as a function that looks like this:
def simple_middleware(get_response):
    # One-time configuration and initialization.

    def middleware(request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = get_response(request)

        # Code to be executed for each request/response after
        # the view is called.

        return response

    return middleware

通过引入一个新的"style",你可以看到旧的中间件本身就是"deprecated",这当然很遗憾,因为现在编写的所有中间件都将失效。

然而 MiddlewareMixin 能够在现代中间件中转换这样的 old 中间件,它通过覆盖 __call__ 函数来实现,因此调用process_requestprocess_response 之间,就像我们在 source code [GitHub]:

中看到的
class MiddlewareMixin:
    def __init__(self, get_response=None):
        self.get_response = get_response
        super().__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, 'process_request'):
            response = self.process_request(request)
        response = response or self.get_response(request)
        if hasattr(self, 'process_response'):
            response = self.process_response(request, response)
        return response

因此,我们在这里通过覆盖 __call__ 函数使对象 可调用 ,从而模仿新样式中 def middleware(request) 的工作方式。然而,如果在旧的中间件中, __call__ 也被覆盖,那么这当然会导致一些问题。此外,旧式中间件有一些功能,如 process_viewprocess_exceptionprocess_template_response,此处不再使用。但我觉得这些都不是很 "popular" 反正。