为啥在 django.utils.deprecation.py 中声明中间件 mixin
Posted
技术标签:
【中文标题】为啥在 django.utils.deprecation.py 中声明中间件 mixin【英文标题】:Why middleware mixin declared in django.utils.deprecation.py为什么在 django.utils.deprecation.py 中声明中间件 mixin 【发布时间】:2019-03-25 14:00:06 【问题描述】:在django.utils.deprecation.py
路径中,我们有一些关于方法弃用警告的类。
在该文件中,我们有一个名为MiddlewareMixin
的类。这个类用来写中间件类。虽然与弃用无关,为什么这个类写在这个路径上?
【问题讨论】:
我认为是因为它将“旧”样式的中间件转换为“新样式”的中间件。 “旧”中间件与process_request
和process_response
一起使用,但“新”中间件本质上是“下层”之上的装饰器。此 mixin 将旧样式(已弃用)转换为新样式。
【参考方案1】:
简而言之:它是一种将已弃用中间件转变为新中间件的工具,尽管它有一些限制。
Django 的中间件“风格”发生了变化。这个MiddlewareMixin
在大多数情况下可以将旧式中间件类“转换”为新式中间件装饰器,正如documentation on Upgrading pre-Django 1.10-style middleware 中所写:
class django.utils.deprecation.MiddlewareMixin
(...)
在大多数情况下,从这个 mixin 继承足以使旧式中间件与新系统兼容,并具有足够的向后兼容性。新的短路语义将对现有的中间件无害甚至有益。在少数情况下,中间件类可能需要进行一些更改以适应新的语义。
在“旧时代”(django-1.10 之前),中间件的写法如下:
class SomeMiddleware:
def process_request(self, request):
# ...
pass
def process_response(self, request, response):
# ...
return response
但如今,中间件更多地被视为围绕“底层中间件”的某种“装饰器”,最终是视图。如documentation on the new middleware中指定:
中间件可以写成如下所示的函数: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
通过引入新的“样式”,您可以看到旧的中间件本身已被“弃用”,这当然是一个遗憾,因为现在所有以前编写的中间件都会被渲染为无效。
MiddlewareMixin
然而能够转换现代中间件中的这种旧中间件,它通过覆盖__call__
函数来实现这一点,因此在两者之间调用process_request
和process_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_view
、process_exception
、process_template_response
等函数,这里不再使用。但我认为无论如何这些都不是很“流行”。
【讨论】:
以上是关于为啥在 django.utils.deprecation.py 中声明中间件 mixin的主要内容,如果未能解决你的问题,请参考以下文章
为啥 CoreGui Roblox 锁定在 DataModel 中,为啥受信任的用户不能使用 CoreScripts?
为啥 + 仅在客户端是 NaN?为啥不在 Node.js 中?
为啥我们不能在 TypeScript 类中定义一个 const 字段,为啥静态只读不起作用?