Bootstrap

Django中间件介绍和使用

中间件

中间件是Django请求/响应处理的钩子框架。这是一个轻量级的低级“插件”系统,用于在全球范围内改变Django的输入或输出。

每个中间件组件都负责完成一些特定的功能。例如,Django包含一个中间件组件 AuthenticationMiddleware,它使用会话将用户与请求相关联。

本文档介绍了中间件如何工作,如何激活中间件以及如何编写自己的中间件。Django附带一些内置的中间件,您可以立即使用它们。它们被记录在内置的中间件参考中

激活中间件

要激活中间件组件,请将其添加到MIDDLEWARE_CLASSESDjango设置中的 列表中。

在中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自上而下地应用中间件两个钩子可用:

在响应阶段,在调用视图之后,中间件从下往上以相反的顺序应用。三个挂钩可供选择:

中间件应用程序

如果你愿意,你也可以把它想象成一个洋葱:每个中间件类都是一个包装视图的“图层”。

每个钩子的行为如下所述。

编写你自己的中间件

编写自己的中间件很容易。每个中间件组件都是一个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_requestprocess_view将阻止任何视图在中间件之后能够修改请求的上传处理程序,并且通常应避免。

CsrfViewMiddleware班可被视为一个例外,因为它提供了 csrf_exempt()与 csrf_protect()装饰允许的意见明确,在应该发生点什么的CSRF验证控制。

process_template_response()

process_template_response 请求 响应

request是一个HttpRequest对象。responseTemplateResponse由Django视图或中间件返回对象(或等价物)。

process_template_response()在视图完成执行后立即调用,如果响应实例有一个render()方法,表明它是一个TemplateResponse或等价的。

它必须返回一个实现render方法的响应对象它可能会改变给定的response改变response.template_nameresponse.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对象。exceptionException视图函数引发的 对象。

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

在Django 1.8中更改:

以前,MiddlewareNotUsed异常未记录。

准则

  • 中间件类不需要任何子类。
  • 中间件类可以在您的Python路径上的任何地方居住。Django关心的是该MIDDLEWARE_CLASSES设置包含了路径。
  • 请随意查看Django可用的中间件以获取示例。
  • 如果您编写一个您认为对其他人有用的中间件组件,请为社区做贡献!让我们知道,我们会考虑将其添加到Django。

;