一、中间件介绍
中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入(请求要先由它处理)和输出(响应也要在最后让它处理)。每个中间件组件都负责做一些特定的功能。
换个直白点的说法:中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作,它本质上就是一个自定义类,类中定义了几个方法,Django框架会在请求的特定的时间去执行这些方法。
涉及全局相关的功能,都可以通过中间件实现,比如:
- 全局用户身份验证;
- 全局用户权限校验;
- 全局用户访问频率监控;
- ……
但是由于其影响的是全局,所以需要谨慎使用,使用不当会影响性能。
1. django默认启用(注册)的中间件
django自带一些中间件,其中有七个是默认就启用的,注册在settings.py文件中的MIDDLEWARE 列表中:
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',
]
这些字符串,实际上一个个路径,最终指向一个类,即中间件。
2. 中间件的顺序
在请求阶段:中间件的执行顺序就是列表中的注册顺序(从上到下);
在响应阶段:中间件的执行顺序就恰好和请求阶段相反(从下到上)。
并且,由于部分中间件之间有依赖关系,例如: AuthenticationMiddleware 需要在会话中间件中存储的经过身份验证的用户信息,因此它必须在 SessionMiddleware 后面运行 。所以,对于django的内置中间件的顺序建议如下:
- SecurityMiddleware
- UpdateCacheMiddleware
- GZipMiddleware
- SessionMiddleware
- ConditionalGetMiddleware
- LocaleMiddleware。
- CommonMiddleware
- CsrfViewMiddleware
- AuthenticationMiddleware
- MessageMiddleware
- FetchFromCacheMiddleware
- FlatpageFallbackMiddleware
- RedirectFallbackMiddleware
以上中间件的说明请参考官方文档:传送门
二、自定义中间件
第一步:在项目目录或app目录下创建一个任意名称的文件夹;
第二步:在文件夹内创建一个任意名称的py文件;
第三步:在py文件内书写类,之后就可以在类中自定义django提供的3个钩子方法(看需要,不一定3个都定义),一定要注意执行顺序编号:
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
"""
:param request: HttpRequest对象
"""
"""
1. 在这里编写刚收到请求,视图和后面的中间件被调用之前需要执行的代码
如果需要可以返回HttpResponse对象,这将直接返回给浏览器,不可以返回其他对象
"""
response = self.get_response(request)
"""
5. 在这里编写视图调用后,返回响应之前需要执行的代码
必须返回response
"""
return response
def process_view(self, request, view_func, view_args, view_kwargs):
"""
2. 执行完__call__方法的前半部分之后,执行视图之前的代码,注意是执行视图之前!
:param request: HttpRequest对象
:param view_func: 真正的视图函数对象(不是函数的字符串名称)
:param view_args: 位置参数列表
:param view_kwargs: 关键字参数字典
:return: None(继续下一步)或者HttpResponse对象(响应内容返回给浏览器)
"""
pass
def process_exception(self,request,exception):
"""
3. 在视图执行过程中,发生异常时执行
:param request: HttpRequest对象
:param exception: 视图引发的异常对象
:return: None(继续下一步)或者HttpResponse对象(响应内容返回给浏览器)
"""
pass
def process_template_response(self, request, response):
"""
4. 视图执行完毕,__call__方法下半部分执行之前执行
:param request: HttpRequest对象
:param response: TemplateResponse 对象
:return: render方法的响应对象
"""
pass
get_response 方法可能是一个实际视图(如果当前中间件是最后列出的中间件),或者是列表中的下一个中间件。我们不需要关心它到底是什么,它只是代表了下一步要进行的操作。
注意:
-
视图抛出异常时,会从下往上依次执行每个中间件中的process_exception 方法。 -
Django仅使用 get_response 参数初始化中间件,因此不能为 __init__() 添加其他参数。 -
与每次请求都会调用 __call__() 方法不同,当 Web 服务器启动后,__init__() 只被调用一次。
第四步:像自带的中间件一样,注册自定义的中间件,路径从项目目录开始,不包括项目目录。
|