python之路_django中间件
中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。如果你想修改请求,例如被传送到view中的HttpRequest对象。 或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现。可能你还想在view执行之前做一些操作,这种情况就可以用 middleware来实现。django中自带如下7个中间件,在setting配置可见,如下:
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中间件
除了django自带如上7种中间件,我们为了满足自己的需求,也可自定义中间件,中间件就是定义一个类,类的下面有四个方法,分别为process_request、process_view、process_exception及process_response,但此类必须但是必须继承MiddlewareMixin,引入方式如下:from
django.utils.deprecation
import
MiddlewareMixin。
自定义中间件实例如下,中间件.py文件必须放在django项目的根目录下,中间件的配置方式与自带中间件配置方式一致。如下实例:
二、中间件执行顺序
1、中间件被执行的顺序
如上,中间件的执行顺序是按照如上中间件配置顺序执行的,从上到下,依次执行中间件中的process_request函数,然后根据url执行所有views视图函数,视图函数执行完后,再从后依次往前执行process_response函数。
但是需要注意,如下为请求的视图函数和自定义的中间件:
views函数:
def index(request): print("view函数...") return HttpResponse("OK")
中间件:
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class Md1(MiddlewareMixin): def process_request(self,request): print("Md1请求") #return HttpResponse("Md1中断") def process_response(self,request,response): print("Md1返回") return response class Md2(MiddlewareMixin): def process_request(self,request): print("Md2请求") def process_response(self,request,response): print("Md2返回") return response
此时输出结果顺序为:
Md1请求
Md2请求
view函数...
Md2返回
Md1返回
但是当把#return HttpResponse("Md1中断")的注释释放,即 process_request请求有返回值时,中间件便不会继续往下走了,视图函数也不会再被执行,会原路返回以上的process_response,次点值得广大读者的注意,这也是自定义中间件一个主要应用点,执行结果为:
Md1请求
Md1返回
二、中间件中的函数执行顺序
如上为中间件的总体执行顺序,但是当中间件中还有process_view和process_exception时,中间件内部函数的总体执行顺序又如何呢?如下为自定义中间件文件及要请求的视图函数:
1、process_view情况
中间件:
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class Md1(MiddlewareMixin): def process_request(self,request): print("Md1请求") #return HttpResponse("Md1中断") def process_response(self,request,response): print("Md1返回") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Md1view") class Md2(MiddlewareMixin): def process_request(self,request): print("Md2请求")def process_response(self,request,response): print("Md2返回") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Md2view")
views函数:
def index(request): print("view函数...") return HttpResponse("OK")
请求后执行的结果为:
Md1请求
Md2请求
Md1view
Md2view
view函数...
Md2返回
Md1返回
由上知道,中间件函数的执行顺序分析图如下:
如上,顺序为:当最后一个中间的process_request到达路由关系映射之后,返回到中间件1的process_view,然后依次往下,到达views函数,最后通过process_response依次返回到达用户。
process_view可以用来调用视图函数:
class Md1(MiddlewareMixin): def process_request(self,request): print("Md1请求") #return HttpResponse("Md1中断") def process_response(self,request,response): print("Md1返回") return response def process_view(self, request, callback, callback_args, callback_kwargs): # return HttpResponse("hello") response=callback(request,*callback_args,**callback_kwargs) return response
结果为:
Md1请求
Md2请求
view函数...
Md2返回
Md1返回
注意:process_view如果有返回值,会越过其他的process_view以及视图函数,但是所有的process_response都还会执行。
2、process_exception情况
自定义中间件:
class Md1(MiddlewareMixin): def process_request(self,request): print("Md1请求") #return HttpResponse("Md1中断") def process_response(self,request,response): print("Md1返回") return response def process_view(self, request, callback, callback_args, callback_kwargs): # return HttpResponse("hello") # response=callback(request,*callback_args,**callback_kwargs) # return response print("md1 process_view...") def process_exception(self): print("md1 process_exception...") class Md2(MiddlewareMixin): def process_request(self,request): print("Md2请求") # return HttpResponse("Md2中断") def process_response(self,request,response): print("Md2返回") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("md2 process_view...") def process_exception(self): print("md1 process_exception...")
执行结果:
Md1请求
Md2请求
md1 process_view...
md2 process_view...
view函数...
Md2返回
Md1返回
由上可见,process_exception函数并没有没执行,为什么呢?因为此函数的是views函数执行出错时候,或者某一个中间件中此函数有返回值时才会被执行,但并不影响这四个函数的总体执行顺序,顺序分析如下: