Middleware中间件

中间件是一个钩子框架,介入到Django的request和response的处理过程中。它是一个 轻量级,低级别的“插件”系统,用于全局的处理Django的输入和(或)输出。

每个中间件组件都是用来完成一些特殊的功能。比如,Django中的一个中间件组建,
XViewMiddleware ,它的功能是给每个HEAD请求的响应增加一个 "X-View"

的HTTP头部。

这篇文档讲解了中间件是如何工作的,如何开启中间件,以及如何编写你自己的中间件。 Django附带一些内置的中间件可以使用开箱即用的,它们被归档在这里: 内置中 间件参考

开启中间件

要开启一个中间件组件,你需要把它添加到你Django settings文件中的 MIDDLEWARE_CLASSES 列表中。在这个列表中,每一个中间件组件用字符串的方式描述:一个完整的Python全路径加上 类的名称。比如,这是默认的中间件,在你用

django-admin.py startproject:: 创建工程的时候自动生成的

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

在request处理的期间 (process_request() and process_view() middleware),Django按照中间件在 :settings:`MIDDLEWARE_CLASSES` 的配置,自上 而下的应用中间件。在一个响应的处理期间 (process_response()

process_exception() 中间件) ,这些中间件类会以相反的顺序被执行,自下

而上。你可以想象它就像洋葱:每个中间件都是包在view上的一层皮:

Middleware application order.
一个Django的程序中中间件不是必需的 –比如,只要你喜欢 MIDDLEWARE_CLASSES
可以是空的,– 但是强烈推荐你至少使用 CommonMiddleware

编写你自己的中间件

编写自己的中间件是很容易的。每个中间件都是一个单独的Python的class,你可以定义 一个或多个下面的这些方法:

process_request

process_request(self, request)

request 是一个 HttpRequest 对象. 这个方法会被 每次请求调用, 在Django决定哪个视图(view)被执行之前。

process_request() 应该返回一个 None 或者一个 HttpResponse 对象. 如果返回一个 ``None``,Django将会继续 处理这个请求,执行其他的middleware并且,然后,显示对应的视图。如果它返回一个

HttpResponse 对象,Django便不再会去调用其他的处理
request,view或者exception的middleware(中间件),或者对应的视图;它会返回
:class:`~django.http.HttpResponse`。处理Response(响应)的middleware会处理任何

返回的response(响应)。

process_view

process_view(self, request, view_func, view_args, view_kwargs)

request 是一个 HttpRequest 对象。 view_func 是 Django将会调用的一个Python的方法。(它确实是一个方法对象,而不是仅仅是以方法 的字符串命名。) view_args 是一个会被传递到视图中的位置参数的列表, view_kwargs 是一个将会被传递到视图中的关键字参数字典。 view_argsview_kwargs 中都不包含视图的第一个参数(request)。

process_view() 会在Django调用视图(view)之前被调用。它应该返回一个 None 或者一个 HttpResponse 对象。如果它返回 None ,Django 将会继续处理这个请求,执行其他的 process_view() 中间件,然后,显示对应的视 图。如果它返回一个 HttpResponse 对象,Django便不再会去调 用其他的处理request,view或者exception的middleware(中间件),或者对应的视图;它会 返回 :class:`~django.http.HttpResponse`。处理Response(响应)的middleware会处理任何 返回的response(响应)。

process_template_response

New in Django 1.3: Please see the release notes
process_template_response(self, request, response)
request 是一个 HttpRequest 对象. response
SimpleTemplateResponse 的一个子类 (例如.

TemplateResponse) 或者说任何一个response 对象都要实现一个 render 方法。

process_template_response() 必须返回一个实现redner方法的response对象。 它可以修改给定的 response 对象,通过修改 response.template_nameresponse.context_data 或者它可以创建一个全新的 SimpleTemplateResponse 或等价的对象。

只有当response实例拥有 render() 方法时 process_template_response() 才会被调用,这表明它是一个 TemplateResponse 类型或者等价类型.

你不需要显式的渲染responses – 一旦所有的模板响应中间件被调用,responses会自动 的被渲染。

在一个响应的处理期间中间件被以相反的顺序运行,这包括 process_template_response Middleware are run in reverse order during the response phase, which includes process_template_response.

process_response

process_response(self, request, response)

request 是一个 HttpRequest 对象。 response 是 被Django的view返回的一个:class:~django.http.HttpResponse 对象。

process_response() 必须返回一个 HttpResponse 对象。 它可以修改已有的 response, 或者创建并返回一个全新的

不像 process_request()process_view() 方法, process_response() 方法总是会被调用, 即使同一个中间件类中的 process_request()process_view() 方法会因为前面的一个中间件返回 HttpResponse 而被跳过。 (这意味着你的 process_response() 方法不能依赖于 process_request() 方法中 的设置,比如)。此外,在一个响应的处理期间,那些类也是以相反的顺序被使用,自下而上的。 这说明在在 MIDDLEWARE_CLASSES 最后的类型被先被执行。

process_exception

process_exception(self, request, exception)

request 是一个 HttpRequest 对象。 exception``是一 个被视图中的方法抛出来的 ``Exception 对象。

当一个视图抛出异常时,Django会调用 process_exception 来处理。 同样,``process_exception()`` 应该返回一个 None 或者一个 HttpResponse 对象。 如果它返回一个 HttpResponse 对象,这个response将会直接返回给浏览器。 否则,默认的异常处理器就开始起作用了。

再次提醒,在处理response期间,中间件的执行顺序是倒序执行的,这包括 process_exception 。如果一个异常处理的中间件返回了一个response,那这个中间件上面的中间件都将不会 被调用。

__init__

大多数的中间件类都不需要一个初始化方法,因为中间件的类定义仅仅是为 process_* 提供一个占位符。如果你确实需要一个全局的状态那就可以通过 __init__ 来加载。然后要铭记如下两个警告:

  • Django初始化你的中间件无需任何参数,因此不要定义一个有参数的 __init__ 方法.
  • 不像 process_* 这种每个request请求过来都要调用的方法一样, __init__ 只会被调用 一次 ,就是在Web服务启动的时候。

标记中间件不被使用

有时在运行时决定是否一个中间件需要被加载是很有用的。在这种情况下,你的中间件 中的 __init__ 方法可以抛出一个 ``django.core.exceptions.MiddlewareNotUsed``异常。这样Django就会从中间件的 处理过程中移除这部分中间件。

指导准则

  • 中间件的类不能是任何类的子类

  • 中间件可以存在与你Python路径中的任何位置。Django所关心的只是被包含在

    MIDDLEWARE_CLASSES 中的配置。

  • Django’s available middleware 当做例子随便 看看。

  • 如果你认为你写的中间件组建可能会对比人有用,那就把它共享到社区!

    Let us know, 并且我们会考虑把

    它添加到Django中。

comments powered by Disqus