中间件
之前我们说django的生命周期:url -> 路由系统 ->函数或者类 -> 返回字符串 或者 模板语言,其实前面还有很多的操作。
django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。
在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下:
settings.py
1 MIDDLEWARE = [ 2 'django.middleware.security.SecurityMiddleware', 3 'django.contrib.sessions.middleware.SessionMiddleware', 4 'django.middleware.common.CommonMiddleware', 5 'django.middleware.csrf.CsrfViewMiddleware', 6 'django.contrib.auth.middleware.AuthenticationMiddleware', 7 'django.contrib.messages.middleware.MessageMiddleware', 8 'django.middleware.clickjacking.XFrameOptionsMiddleware', 9 ]
执行过程:
请求要从中间件穿过,然后返回的时候再从中间件穿出。
自定义中间件
1、创建中间件类
创建一个目录Middle,下面写一个m1.py:
1 from django.utils.deprecation import MiddlewareMixin 2 3 class Row1(MiddlewareMixin): 4 def process_request(self,request): 5 print("first...") 6 7 class Row2(MiddlewareMixin): 8 def process_request(self,request): 9 print("second...") 10 class Row3(MiddlewareMixin): 11 def process_request(self,request): 12 print("third...")
2、注册中间件
1 MIDDLEWARE = [ 2 'django.middleware.security.SecurityMiddleware', 3 'django.contrib.sessions.middleware.SessionMiddleware', 4 'django.middleware.common.CommonMiddleware', 5 'django.middleware.csrf.CsrfViewMiddleware', 6 'django.contrib.auth.middleware.AuthenticationMiddleware', 7 'django.contrib.messages.middleware.MessageMiddleware', 8 'django.middleware.clickjacking.XFrameOptionsMiddleware', 9 'Middle.m1.Row1', 10 'Middle.m1.Row2', 11 'Middle.m1.Row3', 12 ]
view.py:
1 def test(request): 2 print("返回的信息。。。") 3 return HttpResponse('ok')
我们运行,返回的结果是:
这个请求是经过中间件中所有的process_request方法,那也应该有一个response
1 from django.utils.deprecation import MiddlewareMixin 2 3 class Row1(MiddlewareMixin): 4 def process_request(self,request): 5 print("first...") 6 def process_response(self,request,response): 7 print("first response") 8 return response 9 10 class Row2(MiddlewareMixin): 11 def process_request(self,request): 12 print("second...") 13 def process_response(self,request,response): 14 print("second response") 15 return response 16 17 class Row3(MiddlewareMixin): 18 def process_request(self,request): 19 print("third...") 20 def process_response(self,request,response): 21 print("third response") 22 return response
我们要注意,process_response中的参数request,response的名字和顺序都不能够错,否则就会出现错误。
那现在我们来看看我们运行的效果是什么样子的 :
那这个就是中间件执行的顺序过程。
那中间件有什么用呢?
我们可以看到这个参数有request和response,那这个request就是view中的函数中的参数request,我们通过它可以获得method,post值等。所以我们可以做这个样的事情:判断一下发来请求有没有带请求头,如果没有带请求头,那就不需要继续往下走了,直接在中间件中就停止。
比如:我们上面的三个中间件,我们的请求经过了第一个Row1,下面到Row2,如果我们在这里面做一个判断:如果没有带请求头的话就直接return,我们看看怎么执行的?
1 from django.shortcuts import HttpResponse 2 class Row2(MiddlewareMixin): 3 def process_request(self,request): 4 print("second...") 5 return HttpResponse("停止") 6 def process_response(self,request,response): 7 print("second response") 8 return response
你看,这个就直接跳过了third,然后返回
这个就是整个请求周期,我们可以发现在前面还有一大堆的东西挡着,这个中间件适合于对所有的请求进行一个统一的操作,如公共校验,黑名单过滤:获取一下用户的ip,如果在黑名单里就不让它访问,直接在中间件中组织了,没有必要执行下面的操作。
process_view(self, request, callback, callback_args, callback_kwargs)
我们现在在上面的中间件中在加入一个方法process_view:
1 from django.utils.deprecation import MiddlewareMixin 2 3 class Row1(MiddlewareMixin): 4 def process_request(self,request): 5 print("first...") 6 7 def process_view(self, request, view_func, view_func_args, view_func_kwargs): 8 print("first process_view") 9 10 def process_response(self,request,response): 11 print("first response") 12 return response 13 14 from django.shortcuts import HttpResponse 15 class Row2(MiddlewareMixin): 16 def process_request(self,request): 17 print("second...") 18 19 def process_view(self, request, view_func, view_func_args, view_func_kwargs): 20 print("second process_view") 21 22 def process_response(self,request,response): 23 print("second response") 24 return response 25 26 class Row3(MiddlewareMixin): 27 def process_request(self,request): 28 print("third...") 29 30 def process_view(self, request, view_func, view_func_args, view_func_kwargs): 31 print("third process_view") 32 33 def process_response(self,request,response): 34 print("third response") 35 return response
下面我们再来看看执行的结果:
由上面的显示结果我们可以看到的运行流程是,先执行process_request,匹配了url路由之后,折回来在执行process_view,执行views.py中的函数,之后再执行process_response
process_view里面的参数实际上就是views.py里面的函数的函数名和参数,如果我们在url中添加的是正则匹配,那后面就要用一个参数接收一下。
process_exception(self, request, exception)如果views中的函数执行错误了就执行该方法
m1.py
1 class Row3(MiddlewareMixin): 2 def process_request(self,request): 3 print("third...") 4 5 def process_view(self, request, view_func, view_func_args, view_func_kwargs): 6 print("third process_view") 7 8 def process_response(self,request,response): 9 print("third response") 10 return response 11 def process_exception(self, request, exception): 12 if isinstance(exception,ValueError): 13 return HttpResponse("出现异常了。。。。")
views.py:
1 def test(request): 2 int("asdfasdf") 3 print("返回的信息。。。") 4 return HttpResponse('ok')
上面的views.py中的函数很明显有一个错误,如果正常情况下执行肯定会报错,但是我们在中间件中进行了处理,那么我们在执行的时候就会返回一个出现异常。。。。
所以这个东西就可以对异常,报错进行处理,但是如果views.py中没有出错,那么就不会被执行
process_template_response(self,request,response)
默认也不执行,如果views中的函数返回的对象中,具有render方法,那就默认会执行
views.py:
1 class Foo: 2 def render(self): 3 return HttpResponse("ok") 4 def test(request): 5 6 print("返回的信息。。。") 7 return Foo()
m1.py:
1 class Row3(MiddlewareMixin): 2 def process_request(self,request): 3 print("third...") 4 5 def process_view(self, request, view_func, view_func_args, view_func_kwargs): 6 print("third process_view") 7 8 def process_response(self,request,response): 9 print("third response") 10 return response 11 def process_exception(self, request, exception): 12 if isinstance(exception,ValueError): 13 return HttpResponse("出现异常了。。。。") 14 def process_template_response(self,request,response): 15 print("process_template_response函数执行")
return response
运行结果: