Django中的中间件机制
在这篇文章中,将会介绍到以下内容:
- 什么是中间件MiddleWare
- 中间件的运行过程
编写中间件时需要注意的内容
什么是中间件MiddleWare
Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system
for globally altering Django’s input or output.
依照官网的说法,中间件是一种轻量级的插件,每一个中间件在处理Request和Response时会进行一些特定的操作。
主要的内建中间件 参见:
Cache middleware
启用后,所有Django驱动的页面都会被缓存一段时间,时间由
CACHE_MIDDLEWARE_SECONDS
确定,默认为600秒。Common middleware
启用该中间件可以做一些站点的通用配置,如:
- 通过配置
DISALLOWED_USER_AGENTS
,过滤用户的User-Agent - 通过配置
APPEND_SLASH
和PREPEND_WWW
来设置:
- APPEND_SLASH为True并且URL没有以**’/‘结尾的话,没有匹配url时会在结尾加上‘/’**后再次尝试。
- PREPEND_WWW为True的话,会在url前加上www。
- 通过配置
GZip middleware
使用GZip压缩网站内容
Conditional GET middleware
使用条件Get,即:
客户端向服务器发送一个包询问是否在上一次访问网站的时间后是否更改了页面,如果服务器没有更新,显然不需要把整个网页传给客户端,客户端只要使用本地缓存即可,如果服务器对照客户端给出的时间已经更新了客户端请求的网页,则发送这个更新了的网页给用户。Handles conditional GET operations. If the response doesn’t have an
ETag
header, the middleware adds one if needed.
If the response has aETag
orLast-Modified
header, and the request hasIf-None-Match
orIf-Modified-Since
, the
response is replaced by
anHttpResponseNotModified
.Locale middleware
启用后可以做网站本地化(I18N)功能。
Message middleware
启用基于Cookie或者Session的消息机制(同时适用于匿名访问和授权访问)
-
提供几种安全机制,分别通过以下配置项控制
- SECURE_BROWSER_XSS_FILTER
- SECURE_CONTENT_TYPE_NOSNIFF
- SECURE_HSTS_INCLUDE_SUBDOMAINS
- SECURE_HSTS_PRELOAD
- SECURE_HSTS_SECONDS
- SECURE_REDIRECT_EXEMPT
- SECURE_SSL_HOST
- SECURE_SSL_REDIRECT
Session middleware
启用Session支持
Site middleware
在每一个输入的HttpRequest中加入site属性。
Authentication middleware
- AuthenticationMiddleware:在每一个输入的HttpRequest中加入user属性。
- RemoteUserMiddleware:利用Web Server提供认证服务。
- PersistentRemoteUserMiddleware:只在登录页面使用利用Web Server提供认证服务。
CSRF protection middleware
防止跨域访问,避免跨站攻击。
X-Frame-Options middleware
能够在Request/Response的头部加入类似于**X-**开头的头部。
内建中间件的建议排序方式
-
It should go near the top of the list if you’re going to turn on the SSL redirect as that avoids running through a
bunch of other unnecessary middleware. -
Before those that modify the
Vary
header (SessionMiddleware
,GZipMiddleware
,LocaleMiddleware
). -
Before any middleware that may change or use the response body.
After
UpdateCacheMiddleware
: ModifiesVary
header. -
Before
CommonMiddleware
: uses itsETag
header
whenUSE_ETAGS
=True
. -
After
UpdateCacheMiddleware
: ModifiesVary
header. -
One of the topmost, after
SessionMiddleware
(uses session data) andUpdateCacheMiddleware
(modifiesVary
header). -
Before any middleware that may change the response (it sets the
ETag
andContent-Length
headers). A middleware
that appears beforeCommonMiddleware
and changes the response must reset the headers.After
GZipMiddleware
so it won’t calculate anETag
header on gzipped contents.Close to the top: it redirects
whenAPPEND_SLASH
orPREPEND_WWW
are set toTrue
. -
Before any view middleware that assumes that CSRF attacks have been dealt with.
It must come after
SessionMiddleware
if you’re
usingCSRF_USE_SESSIONS
. -
After
SessionMiddleware
: uses session storage. -
After
SessionMiddleware
: can use session-based storage. -
After any middleware that modifies the
Vary
header: that header is used to pick a value for the cache hash-key. -
Should be near the bottom as it’s a last-resort type of middleware.
-
Should be near the bottom as it’s a last-resort type of middleware.
中间件的运行过程
以函数(方法)的方式定义中间件
1 | def simple_middleware(get_response): |
以类的方式定义中间件
1 | class SimpleMiddleware: |
### 将中间件标记为未使用
在__init__()
中抛出MiddlewareNotUsed
异常将会从Django中移除这个中间件,同时,如果DEBUG
配置开启(为True
)的话,会在django.request中
打印出日志信息。
激活中间件
在配置文件中添加MIDDLEWARE
列表,列表中的中间件将会按照顺序执行。默认为:
1 | MIDDLEWARE = [ |
其他的中间件钩子
- ***Process_view()***:在调用正常的
view
之前调用。- process_view(request, view_func, view_args, view_kwargs)
- ***process_exception()***:处理
view
中抛出的异常。- process_exception(request, exception)
- ***process_template_response()***:返回一个
TemplateResponse
对象。- process_template_response(request, response)
老版本的Django使用的中间件定义方式
1 | class AnotherMiddleware(object): |
Django按照配置文件中的配置顺序调用process_request,然后请求view,获取response,在按照配置反向顺序调用
process_response。
兼容老版本的定义方式
新版本定义过程中可以使用继承class django.utils.deprecation.MiddlewareMixin
的方式来兼容老版本的中间件。
1 | class MiddlewareMixin: |
主要进行了以下操作:
- Calls
self.process_request(request)
(if defined).- Calls
self.get_response(request)
to get the response from later middleware and the view.- Calls
self.process_response(request, response)
(if defined).- Returns the response.
编写中间件时需要注意的内容
middlewares
的顺序非常重要一个middleware
只需要继承object
类- 一个
middleware
可以实现一些方法并且不需要实现所有的方法 - 一个
middleware
可以实现process_request
(方法)但是不实现process_response
(方法) 和process_view
方法。
这些都很常见,Django提供了很多middlewares
可以做到。AuthenticationMiddleware
只实现了对请求的处理,并没有处理响应.参照文档
- 一个
middleware
可以实现process_response
方法,但是不实现process_request
方法GZipMiddleware
只实现了对响应的处理,并没有实现对请求和view的处理参见文档
Django中的中间件机制