django

Django中间件

2018-03-24  本文已影响166人  大爷的二舅

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

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

本文档介绍了中间件的工作方式,如何激活中间件以及如何编写自己的中间件。 Django附带一些内置的中间件,您可以立即使用它们。 请参阅本章稍后的“可用中间件”。

激活中间件

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

在MIDDLEWARE_CLASSES中,每个中间件组件都由一个字符串表示:中间件类名的完整Python路径。 例如,以下是由django-admin startproject创建的默认值:

MIDDLEWARE_CLASSES = [
    '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',
]

Django安装不需要任何中间件 - 如果您愿意,MIDDLEWARE_CLASSES可以为空 - 但强烈建议您至少使用CommonMiddleware。

MIDDLEWARE_CLASSES中的顺序很重要,因为中间件可以依赖于其他中间件。 例如,AuthenticationMiddleware将认证用户存储在会话中; 因此,它必须在SessionMiddleware之后运行。 有关Django中间件类的排序的一些常见提示,请参阅本章后面的“中间件排序”。

挂钩和应用程序订单

在请求阶段,在调用视图之前,Django按照MIDDLEWARE_CLASSES中自上而下的顺序应用中间件。 两个钩子可用:

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

如果你愿意,你也可以把它想象成一个洋葱:每个中间件类都是一个包装视图的图层。 每个钩子的行为如下所述。

编写自己的中间件

编写自己的中间件很容易。 每个中间件组件都是一个Python类,它定义了以下一种或多种方法:

process_request

方法:process_request(request)

它应该返回None或HttpResponse对象。 如果返回None,Django将继续处理该请求,执行任何其他process_request()中间件,然后执行process_view()中间件,最后执行相应的视图。

如果它返回一个HttpResponse对象,Django不会打扰任何其他请求,视图或异常中间件或适当的视图; 它会将响应中间件应用于该HttpResponse,并返回结果。

process_view

方法:process_view(request,view_func,view_args,view_kwargs)

如果它返回一个HttpResponse对象,Django不会打扰调用任何其他视图或异常中间件或适当的视图; 它会将响应中间件应用于该HttpResponse,并返回结果。

在中间件内部从process_request或process_view访问request.POST会阻止任何视图在中间件能够修改请求的上传处理程序之后运行,并且通常应该避免。

CsrfViewMiddleware类可以被认为是一个例外,因为它提供了csrf_exempt()和csrf_protect()装饰器,它们允许视图明确地控制CSRF验证应该发生在哪一点。

process_template_response

方法:process_template_response(request,response)

它必须返回一个实现渲染方法的响应对象。 它可以通过改变response.template_name和response.context_data来改变给定的响应,或者它可以创建并返回一个全新的TemplateResponse或等价物。

您不需要明确呈现响应 - 响应将在所有模板响应中间件被调用后自动呈现。

中间件在响应阶段以相反的顺序运行,其中包括process_template_response()。

process_response

方法: process_response(request, response)

与process_request()和process_view()方法不同,即使跳过同一中间件类的process_request()和process_view()方法(因为较早的中间件方法返回了HttpResponse),process_response()方法也会始终被调用。 特别是,这意味着您的process_response()方法不能依赖process_request()中完成的设置。

最后,请记住,在响应阶段,中间件以相反的顺序应用,从下到上。 这意味着在MIDDLEWARE_CLASSES结尾定义的类将首先运行。

处理流式响应

与HttpResponse不同,StreamingHttpResponse没有内容属性。 因此,中间件不能再假设所有的响应都会有一个内容属性。 如果他们需要访问内容,他们必须测试流式响应并相应地调整其行为:

if response.streaming:
   response.streaming_content = wrap_streaming_content(response.streaming_content)
else:
   response.content = alter_content(response.content)

应该假定streaming_content太大而不能保存在内存中。 响应中间件可以将其包装在新的生成器中,但不能使用它。 包装通常如下实施:

def wrap_streaming_content(content):
    for chunk in content:
        yield alter_content(chunk)

#######process_exception
方法:process_exception(request,exception)

中间件再一次在响应阶段以相反的顺序运行,其中包括process_exception。 如果异常中间件返回响应,则该中间件上的中间件类将不会被调用。

__init__

大多数中间件类不需要初始化器,因为中间件类基本上是process_ *methods的占位符。 如果你确实需要一些全局状态,你可以使用__init__来设置。 不过,请记住一些注意事项:

  1. Django无需任何参数即可初始化您的中间件,因此您无法将__init__定义为需要任何参数。
  2. 与每个请求调用一次的process_ *方法不同,当Web服务器响应第一个请求时,__init__只会被调用一次。
将中间件标记为未使用

在运行时确定是否应使用中间件有时很有用。 在这些情况下,您的中间件的init方法可能会引发django.core.exceptions.MiddlewareNotUsed。 然后,Django将从中间件进程中移除该中间件,并在DEBUG设置为True时将调试消息记录到django.request记录器中。

附加指南
上一篇 下一篇

猜你喜欢

热点阅读