它的返回值可以是None也可以是HttpResponse对象。返回值是None的话,按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象,Django将不执行视图函数,而将相应对象返回给浏览器。
我们来看看多个中间件时,Django是如何执行其中的process_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") pass在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', 'middlewares.MD1', # 自定义中间件MD1,这个写的是你项目路径下的一个路径,例如,如果你放在项目下,文件夹名成为utils,那么这里应该写utils.middlewares.MD1 'middlewares.MD2' # 自定义中间件MD2 ]此时,我们访问一个视图,会发现终端中打印如下内容:
MD1里面的 process_request MD2里面的 process_requestapp01 中的 index视图把MD1和MD2的位置调换一下,再访问一个视图,会发现终端中打印的内容如下:
MD2里面的 process_request MD1里面的 process_requestapp01 中的 index视图看结果我们知道:视图函数还是最后执行的,MD2比MD1先执行自己的process_request方法。
在打印一下两个自定义中间件中process_request方法中的request参数,会发现它们是同一个对象。
由此总结一下:
中间件的process_request方法是在执行视图函数之前执行的。
当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是列表的索引值,从前到后依次执行的。
不同中间件之间传递的request都是同一个对象
多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的,也就是说第一个中间件的process_request方法首先执行,而它的process_response方法最后执行,最后一个中间件的process_request方法最后一个执行,它的process_response方法是最先执行。
process_response它有两个参数,一个是request,一个是response,request就是上述例子中一样的对象,response是视图函数返回的HttpResponse对象。该方法的返回值也必须是HttpResponse对象。
给上述的M1和M2加上process_response方法:
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("MD1里面的 process_request") #不必须写return值 def process_response(self, request, response):#request和response两个参数必须有,名字随便取 print("MD1里面的 process_response") #print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容的方法,或者直接使用response.content也可以看到响应体里面的内容,由于response是个变量,直接点击看源码是看不到的,你打印type(response)发现是HttpResponse对象,查看这个对象的源码就知道有什么方法可以用了。 return response #必须有返回值,写return response ,这个response就像一个接力棒一样 #return HttpResponse('瞎搞') ,如果你写了这个,那么你视图返回过来的内容就被它给替代了 class MD2(MiddlewareMixin): def process_request(self, request): print("MD2里面的 process_request") pass def process_response(self, request, response): #request和response两个参数必须要有,名字随便取 print("MD2里面的 process_response") return response #必须返回response,不然你上层的中间件就没有拿到httpresponse对象,就会报错访问一个视图,看一下终端的输出:
MD2里面的 process_request MD1里面的 process_request app01 中的 index视图 MD1里面的 process_response MD2里面的 process_response看结果可知:
process_response方法是在视图函数之后执行的,并且顺序是MD1比MD2先执行。(此时settings.py中 MD2比MD1先注册)
多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的,也就是说第一个中间件的process_request方法首先执行,而它的process_response方法最后执行,最后一个中间件的process_request方法最后一个执行,它的process_response方法是最先执行。