中间件介绍
Django中间件是django的门户。它可以用来在全局范围内改变Django的输入和输出,每个中间件都负责做一些特定的功能。
比如:全局用户身份校验,全局用户访问频率校验,用户访问黑名单。
说的直白一点:中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作
只要以后用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', ]
自定义中间件
中间件可以定义五个方法,分别是:(主要的是process_request和process_response)
- process_request(self,request)
- process_view(self, request, view_func, view_args, view_kwargs)
- process_template_response(self,request,response)
- process_exception(self, request, exception)
- process_response(self, request, response)
重要的两个方法
process_request:
它的返回值可以是None也可以是HttpResponse对象。返回值是None的话,按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象,Django将不执行视图函数,而将相应对象返回给浏览器。
由此总结一下:
- 中间件的process_request方法是在执行视图函数之前执行的。
- 当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是从上到下依次执行的。
- 不同中间件之间传递的request都是同一个对象
request_response:
多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的。
定义process_response方法时,必须给方法传入两个形参,request和response,并且需要将形参response返回。
如果你内部自己返回了HttpResponse对象 会将返回给用户浏览器的内容替换成你自己的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class MD1(MiddlewareMixin): def process_request(self, request): print("MD1里面的 process_request") def process_response(self, request, response): print("MD1里面的 process_response") return response class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request") pass def process_response(self, request, response): print("MD2里面的 process_response") return response
终端输出:
MD1里面的 process_request
MD2里面的 process_request
app01 中的 index视图
MD2里面的 process_response
MD1里面的 process_response
需要了解的三个方法
process_view
此方法是在Django路由系统匹配成功之后,视图系统之前执行的,执行顺序按照MIDDLEWARE中的注册顺序从前到后顺序执行的
process_template_response
process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class MD1(MiddlewareMixin): def process_request(self, request): print("MD1里面的 process_request") def process_response(self, request, response): print("MD1里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD1 中的process_view") print(view_func, view_func.__name__) def process_template_response(self, request, response): print("MD1 中的process_template_response") return response class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request") pass def process_response(self, request, response): print("MD2里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("MD2 中的process_view") print(view_func, view_func.__name__) def process_template_response(self, request, response): print("MD2 中的process_template_response") return response
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def index(request): print("app01 中的 index视图") def render(): print("in index/render") return HttpResponse("O98K") rep = HttpResponse("OK") rep.render = render return rep
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
MD1里面的 process_request MD2里面的 process_request -------------------------------------------------------------------------------- MD1 中的process_view <function index at 0x000001C111B97488> index -------------------------------------------------------------------------------- MD2 中的process_view <function index at 0x000001C111B97488> index app01 中的 index视图 MD2 中的process_template_response MD1 中的process_template_response in index/render MD2里面的 process_response MD1里面的 process_response
process_exception
当视图函数报错的时候自动触发,它的执行顺序也是按照中间件注册顺序的倒序执行。