中间件¶
中间件是Django请求/响应处理的钩子框架。这是一个轻量级的低级“插件”系统,用于在全球范围内改变Django的输入或输出。
每个中间件组件都负责完成一些特定的功能。例如,Django包含一个中间件组件 AuthenticationMiddleware
,它使用会话将用户与请求相关联。
本文档介绍了中间件如何工作,如何激活中间件以及如何编写自己的中间件。Django附带一些内置的中间件,您可以立即使用它们。它们被记录在内置的中间件参考中。
激活中间件¶
要激活中间件组件,请将其添加到MIDDLEWARE_CLASSES
Django设置中的 列表中。
在中MIDDLEWARE_CLASSES
,每个中间件组件都由一个字符串表示:中间件类名的完整Python路径。例如,以下是由以下项创建的默认值:django-admin startproject
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware' ,
'django.contrib.sessions.middleware.SessionMiddleware' ,
'django.middleware.common.CommonMiddleware' ,
'django.middleware.csrf.CsrfViewMiddleware' ,
''django.contrib。 auth.middleware.AuthenticationMiddleware' ,
'django.contrib.auth.middleware.SessionAuthenticationMiddleware' ,
'django.contrib.messages.middleware.MessageMiddleware' ,
'django.middleware.clickjacking.XFrameOptionsMiddleware' ,
]
Django安装不需要任何中间件 - MIDDLEWARE_CLASSES
如果您愿意,可以是空的 - 但强烈建议您至少使用 CommonMiddleware
。
MIDDLEWARE_CLASSES
由于中间件可以依赖于其他中间件,因此这个顺序很重要。例如, AuthenticationMiddleware
将认证用户存储在会话中; 因此,它必须在之后运行 SessionMiddleware
。有关Django中间件类的排序的一些常见提示,请参阅 中间件排序。
挂钩和应用程序¶
在请求阶段,在调用视图之前,Django按照自定义的顺序MIDDLEWARE_CLASSES
自上而下地应用中间件。两个钩子可用:
在响应阶段,在调用视图之后,中间件从下往上以相反的顺序应用。三个挂钩可供选择:
process_exception()
(只有当视图引发异常时)process_template_response()
(仅适用于模板响应)process_response()
如果你愿意,你也可以把它想象成一个洋葱:每个中间件类都是一个包装视图的“图层”。
每个钩子的行为如下所述。
编写你自己的中间件¶
编写自己的中间件很容易。每个中间件组件都是一个Python类,它定义了以下一种或多种方法:
process_request()
¶
process_request
(
请求
)
¶
request
是一个HttpRequest
对象。
process_request()
在Django决定执行哪个视图之前,每个请求都会调用它。
它应该返回一个None
或一个HttpResponse
对象。如果它返回None
,Django将继续处理此请求,执行任何其他process_request()
中间件,然后执行process_view()
中间件,最后执行相应的视图。如果它返回一个 HttpResponse
对象,Django不会打扰任何其他请求,视图或异常中间件或适当的视图; 它会将响应中间件应用于此HttpResponse
,并返回结果。
process_view()
¶
process_view
(
request
,
view_func
,
view_args
,
view_kwargs
)
¶
request
是一个HttpRequest
对象。view_func
是Django即将使用的Python函数。(它是实际的函数对象,而不是作为字符串函数的名称)view_args
是将传递给视图的位置参数列表,并且view_kwargs
是将传递给视图的关键字参数的字典。既不 包含view_args
也不view_kwargs
包含第一个视图参数(request
)。
process_view()
在Django调用视图之前调用。
它应该返回一个None
或一个HttpResponse
对象。如果它返回None
,Django将继续处理此请求,执行任何其他process_view()
中间件,然后执行相应的视图。如果它返回一个HttpResponse
对象,Django不会打扰任何其他视图或异常中间件或适当的视图; 它会将响应中间件应用于此 HttpResponse
,并返回结果。
注意
request.POST
在中间件内部访问中间件process_request
或process_view
将阻止任何视图在中间件之后能够修改请求的上传处理程序,并且通常应避免。
该CsrfViewMiddleware
班可被视为一个例外,因为它提供了 csrf_exempt()
与 csrf_protect()
装饰允许的意见明确,在应该发生点什么的CSRF验证控制。
process_template_response()
¶
process_template_response
(
请求
,
响应
)
¶
request
是一个HttpRequest
对象。response
是TemplateResponse
由Django视图或中间件返回的对象(或等价物)。
process_template_response()
在视图完成执行后立即调用,如果响应实例有一个render()
方法,表明它是一个TemplateResponse
或等价的。
它必须返回一个实现render
方法的响应对象。它可能会改变给定的response
改变response.template_name
和response.context_data
,它也可以创建并返回一个全新的 TemplateResponse
或等同。
您不需要明确呈现响应 - 响应将在所有模板响应中间件被调用后自动呈现。
中间件在响应阶段以相反的顺序运行,其中包括process_template_response()
。
process_response()
¶
process_response
(
请求
,
响应
)
¶
request
是一个HttpRequest
对象。response
是由Django视图或中间件返回的HttpResponse
或 StreamingHttpResponse
对象。
process_response()
在所有响应返回浏览器之前被调用。
它必须返回一个HttpResponse
或 一个StreamingHttpResponse
对象。它可以改变给定的 response
,或者它可以创建并返回一个全新的 HttpResponse
或 StreamingHttpResponse
。
不像process_request()
和process_view()
方法,该 process_response()
方法总是调用,即使 process_request()
和process_view()
同中间件类的方法跳过的(因为先前的中间件方法返回的 HttpResponse
)。特别是,这意味着你的process_response()
方法不能依赖于在中完成的设置 process_request()
。
最后,请记住,在响应阶段,中间件以相反的顺序应用,从下到上。这意味着最后定义的类 MIDDLEWARE_CLASSES
将首先运行。
处理流式响应¶
不像HttpResponse
, StreamingHttpResponse
没有content
属性。因此,中间件不能再假设所有的响应都会有一个content
属性。如果他们需要访问内容,他们必须测试流式响应并相应地调整其行为:
如果 回应。streaming :
响应。streaming_content = wrap_streaming_content (响应。streaming_content )
其他:
响应。content = alter_content (response . content )
注意
streaming_content
应该被认为太大而不能保持在记忆中。响应中间件可以将其包装在新的生成器中,但不能使用它。包装通常如下实施:
DEF wrap_streaming_content (内容):
对于 块 中 的内容:
收率 alter_content (块)
process_exception()
¶
process_exception
(
请求
,
例外
)
¶
request
是一个HttpRequest
对象。exception
是Exception
视图函数引发的 对象。
Django process_exception()
在视图引发异常时调用。 process_exception()
应该返回一个None
或一个 HttpResponse
对象。如果它返回一个 HttpResponse
对象,则将应用模板响应和响应中间件,并将生成的响应返回给浏览器。否则,默认的异常处理就开始了。
中间件再一次在响应阶段以相反的顺序运行,其中包括process_exception
。如果异常中间件返回响应,则该中间件上的中间件类将不会被调用。
__init__()
¶
大多数中间件类不需要初始化器,因为中间件类基本上是process_*
方法的占位符。如果您确实需要一些可用于__init__
设置的全局状态。不过,请记住一些注意事项:
- Django无需任何参数即可初始化您的中间件,因此您无法将其定义
__init__
为需要任何参数。 - 与
process_*
每个请求调用一次的方法 不同,当Web服务器响应第一个请求时,__init__
只调用一次。
将中间件标记为未使用¶
在运行时确定是否应使用中间件有时很有用。在这些情况下,您的中间件的__init__
方法可能会升高django.core.exceptions.MiddlewareNotUsed
。然后,Django将从中间件进程中移除该中间件,并在设置为时将调试消息记录到django.request
记录器DEBUG
中 True
。
以前,MiddlewareNotUsed
异常未记录。
准则¶
- 中间件类不需要任何子类。
- 中间件类可以在您的Python路径上的任何地方居住。Django关心的是该
MIDDLEWARE_CLASSES
设置包含了路径。 - 请随意查看Django可用的中间件以获取示例。
- 如果您编写一个您认为对其他人有用的中间件组件,请为社区做贡献!让我们知道,我们会考虑将其添加到Django。