中间件的执行流程
image.png image.png请求进来之后,会依次的区执行中间的相应方法,然后返回的时候,也需要执行中间件的方法。
第一个方法:
process_request方法:
在 settings.py 中的 MIDDLEWARE 里注册自定义的中间件类:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', # 内置的安全机制,保护用户与网站的通信安全。
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', # 开启CSRF防护功能
'django.contrib.auth.middleware.AuthenticationMiddleware', # 开启内置的用户认证系统
'django.contrib.messages.middleware.MessageMiddleware', # 开启内置的信息提示功能
'django.middleware.clickjacking.XFrameOptionsMiddleware', # 防止恶意程序点击劫持
'app01.migrations.MD1',
'app01.migrations.MD2',
]
自定义中间件类的方法
自定义中间件类的方法有:process_request 和 process_response
process_request 方法
process_request 方法有一个参数 request,这个 request 和视图函数中的 request 是一样的。
process_request 方法的返回值可以是 None 也可以是 HttpResponse 对象。
- 返回值是 None 的话,按正常流程继续走,交给下一个中间件处理。
- 返回值是 HttpResponse 对象,Django 将不执行后续视图函数之前执行的方法以及视图函数,直接以该中间件为起点,倒序执行中间件,且执行的是视图函数之后执行的方法。
场景:可以执行一些初始化的操作,比如用户是否登录,用户是否有权限访问等,常用于前后端分离的业务。前端在去调后端的接口时候,我们一般会用jwt封装数据给后端,后端在中间件层拿到jwt,然后进行解析,判断是否有权限。
process_request 方法是在视图函数之前执行的。
当配置多个中间件时,会按照 MIDDLEWARE中 的注册顺序,也就是列表的索引值,顺序执行。
不同中间件之间传递的 request 参数都是同一个请求对象。
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1.process_request")
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2.process_request")
process_response
process_response 方法有两个参数,一个是 request,一个是 response,request 是请求对象,response 是视图函数返回的 HttpResponse 对象,该方法必须要有返回值,且必须是response。
process_response 方法是在视图函数之后执行的。
当配置多个中间件时,会按照 MIDDLEWARE 中的注册顺序,也就是列表的索引值,倒序执行
class MD1(MiddlewareMixin):
def process_request(self, request):
print("md1 process_request 方法。", id(request)) # 在视图之前执行
def process_response(self,request, response): # 基于请求响应
print("md1 process_response 方法!", id(request)) # 在视图之后
return response
从下图看,正常的情况下按照绿色的路线进行执行,假设中间件1有返回值,则按照红色的路线走,直接执行该类下的 process_response 方法返回,后面的其他中间件就不会执行。
image.png
process_view
process_view 方法格式如下:
process_view(self, request, view_func, view_args, view_kwargs)
process_view 方法有四个参数:
- request 是 HttpRequest 对象。
- view_func 是 Django 即将使用的视图函数。
- view_args 是将传递给视图的位置参数的列表。
- view_kwargs 是将传递给视图的关键字参数的字典。
view_args 和 view_kwargs 都不包含第一个视图参数(request)。
process_view 方法是在视图函数之前,process_request 方法之后执行的。
返回值可以是 None、view_func(request) 或 HttpResponse 对象。
- 返回值是 None 的话,按正常流程继续走,交给下一个中间件处理。
- 返回值是 HttpResponse 对象,Django 将不执行后续视图函数之前执行的方法以及视图函数,直接以该中间件为起点,倒序执行中间件,且执行的是视图函数之后执行的方法。
- c.返回值是 view_func(request),Django 将不执行后续视图函数之前执行的方法,提前执行视图函数,然后再倒序执行视图函数之后执行的方法。
- 当最后一个中间件的 process_request 到达路由关系映射之后,返回到第一个中间件 process_view,然后依次往下,到达视图函数。
class MD1(MiddlewareMixin):
def process_request(self, request):
print("md1 process_request 方法。", id(request)) # 在视图之前执行
def process_response(self,request, response): # 基于请求响应
print("md1 process_response 方法!", id(request)) # 在视图之后
return response
def process_view(self,request, view_func, view_args, view_kwargs):
print("md1 process_view 方法!") # 在视图之前执行 顺序执行
#return view_func(request)
image.png
process_exception
process_exception 方法如下:
process_exception(request, exception)
作用:全局的处理异常的方法
条件:业务函数如果出现错误时候、中间件会通过process_exception捕获
def process_exception(self, request, exception):
err_info = traceback.format_exc()
return HttpResponse(err_info)
参数说明:
- request 是 HttpRequest 对象。
- exception 是视图函数异常产生的 Exception 对象。
process_exception 方法只有在视图函数中出现异常了才执行,按照 settings 的注册倒序执行。
在视图函数之后,在 process_response 方法之前执行。
process_exception 方法的返回值可以是一个 None 也可以是一个 HttpResponse 对象。
返回值是 None,页面会报 500 状态码错误,视图函数不会执行。
process_exception 方法倒序执行,然后再倒序执行 process_response 方法。
返回值是 HttpResponse 对象,页面不会报错,返回状态码为 200。
视图函数不执行,该中间件后续的 process_exception 方法也不执行,直接从最后一个中间件的 process_response 方法倒序开始执行。
具体例子
class MD1(MiddlewareMixin):
def process_request(self, request):
print("md1 process_request 方法。", id(request)) # 在视图之前执行
def process_response(self,request, response): # 基于请求响应
print("md1 process_response 方法!", id(request)) # 在视图之后
return response
def process_view(self,request, view_func, view_args, view_kwargs):
print("md1 process_view 方法!") # 在视图之前执行 顺序执行
#return view_func(request)
def process_exception(self, request, exception):#引发错误 才会触发这个方法
print("md1 process_exception 方法!")
# return HttpResponse(exception) # 返回错误信息
网友评论