Django中间件
一、什么是中间件
中间件是Django请求/响应处理的钩子框架。这是一个轻量级的低级"插件"系统,用于在全球范围内改变Django的输入或输出。 每个中间件组件都负责完成一些特定的功能。例如,Django包含一个组件AuthenticationMiddleware,它使用会话将用户与请求相关联。
二、编写自己的中间件
中间件是可调用的,它可以get_response调用并返回一个中间件。中间件是一种可调用的方法,它接受请求并返回响应,就像视图一样。
中间件可以写成如下所示的函数:
def simple_middleware(get_response): # 一次性匹配和初始化 def middleware(request): # 代码之前要为每个请求执行 # 视图(和后来的中间件)被调用 response = get_response(request) # 代码将在每个请求/响应之后执行 # 视图被调用. return response return middleware
或者它可以写成一个实例可调用的类,如下所示:
class SimpleMiddleware(object): def __init__(self, get_response): self.get_response = get_response # 一次性配置和初始化. def __call__(self, request): # 代码之前要为每个请求执行 # 视图(和后来的中间件)被调用. response = self.get_response(request) # 代码将在每个请求/响应之后执行 # 视图被调用. return response
get_responseDjango提供的可调用可能是实际的视图(如果这是最后列出的中间件),或者它可能是链中的下一个中间件。目前的中间件不需要知道或关心它到底是什么,只是表示接下来的任何事情。
以上是一个小小的简化-get_response链中最后一个中间件的可调用不会是实际视图,而是来自处理器的装饰器方法,该方法负责应用视图中间件,使用适当的URL参数使用视图并应用模版-响应和异常中间件。
自己写的中间件可以放在Python项目上的任何路径上。
__init__(get_response)
中间件必须接受一个get_response参数。请记住一些注意事项:
- Django只使用get_response参数初始化中间件,因此您不能将其定义__init__()为需要任何其他参数。
- 与__call__()每个请求__init__()只调用一次的方法不同,Web服务器启动时只调用一次。
三、激活中间件
要激活中间件组件,请将其添加到Django——settings.py——MIDDLEWARE列表中。
在MIDDLEWARE中,每个中间件组件都由一个字符表示:到中间件的类或函数名称的完整Python路径。
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', '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,可以是空的,但是强烈建议至少使用CommonMiddleware。
MIDDLEWARE由于中间件可以依赖于其他中间件,因此这个顺序很重要。例如,AuthenticationMiddleware将认证用户存储在会话中;因此,它必须在SessionMiddleware之后运行。更多有关Django中间件类的排序的一些常见提示,请参阅中间件排序。
四、中间件的顺序和分层
在请求阶段,在调用视图之前,Django按照自定义的顺序MIDDLEWARE自上而下地应用中间件。
你可以把它想象成一个洋葱:每个中间件类都是一个包装视图的“图层”,它是洋葱的核心。如果请求通过洋葱的所有层(每个层都调用get_response将请求传递到下一层),一直到核心层的视图,则响应将通过每层(按相反顺序)退出的方式。
如果其中一个层决定短路并返回响应而没有调用它get_response,那么该层内的洋葱(包括视图)都不会看到请求或响应。响应只会通过传入请求的相同层返回。
五、其他中间件
除了前面描述的基本请求/响应中间件模式之外,还可以将其他三种特殊方法添加到基于类的中间件:
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_view()会阻止任何视图在中间件能够修改请求的上传处理程序之后运行,并且通常应避免。
该CsrfViewMiddleware可被视为一个例外,因为它提供了csrf_exempt()与csrf_protect()装饰允许的意见明确,在应该发生点什么的CSRF验证控制。
process_exception()
process_exception(request, exception)
request是一个HttpRequest对象。exception是Exception视图函数引发的对象。
Django process_exception()在视图引发异常时调用。process_exception()应该返回一个None或一个HttpResponse对象。如果它返回一个HttpResponse对象,则将应用模版响应和响应中间件,并将返回的结果返回给浏览器。否则,默认的异常处理就开始了。
中间件再一次在响应阶段以相反的顺序允许,其中包括process_exception。如果异常中间件返回响应,那么process_exception中间件上方的中间件类的方法根本不会被调用。
process_template_response()
process_template_response(request, response)
request是一个HttpRequest对象。response是TemplateResponse由Django视图或中间件返回的对象(或等价物)。
process_template_response()在视图完成执行后立即调用,如果响应实例有一个render()方法,表明它是一个TemplateResponse或等价的。
它必须返回一个实现render方法的响应对象。它可能会改变给定的response改变response.template_name和response.context_data,它也可以创建并返回一个全新的TemplateResponse或等同。