python Django 中间件介绍
我们一直都在使用中间件,只是没有注意到而已,打开Django项目的Settings.py文件,看到下面的MIDDLEWARE配置项,django默认自带的一些中间件:
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',
'utils.middlewares.MD1',
'utils.middlewares.MD2'
]
我们之前已经接触过一个csrf相关的中间件了?我们一开始让大家把他注释掉,再提交post请求的时候,就不会被forbidden了,后来学会使用csrf_token之后就不再注释这个中间件了。
中间件可以定义五个方法,分别是:(主要的是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)
以上方法的返回值可以是None或一个HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户。
当用户发起请求的时候会依次经过所有的的中间件,这个时候的请求时process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者。
上述截图中的中间件都是django中的,我们也可以自己定义一个中间件,我们可以自己写一个类,但是必须继承MiddlewareMixin
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self,request): print(id(request)) print('from MD1 process_request') # return HttpResponse("HHHHH") # return None def process_response(self,request,response): # print(id(response)) print('from MD1 process_response') return response #---------------------------------------------------- class MD2 (MiddlewareMixin): def process_request(self, request): # print(id(request)) print('from MD2 process_request') def process_response(self, request, response): # print(id(response)) print('from MD2 process_response') return response
- 执行时间:在视图函数执行之后
- 参数:request -->> 与视图函数中的是同一个 /response-->>视图函数中传递的响应对象
- 执行顺序:按照注册顺序,倒叙执行
- 返回值:HttpResponse对象:必须是响应对象
process_view
process_view(self, request, view_func, view_args, view_kwargs)
执行时间:在process_request方法之后,在视图函数执行之前
参数:
- request -->> 跟视图函数中的是同一个
- view_func -->> 视图函数
- view_args -->> 视图函数的位置参数
- view_kwargs-->> 视图函数的关键字参数
执行顺序:按照注册顺序 顺序执行
返回值:None: 正常流程
HttpResponse对象:不执行后面中间中的process_view方法,不执行视图函数,直接执行最后一个中间件中的process_response方法,后面正常走
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self,request): print(id(request)) print('from MD1 process_request') # return HttpResponse("HHHHH") # return None def process_response(self,request,response): # print(id(response)) print('from MD1 process_response') return response def process_view(self,request,view_func,view_args,view_kwargs): # print(view_func) # print(view_args) # print(view_kwargs) print('from MD1 process_view') # return HttpResponse('kkkkkk') def process_exception(self,request,exception): print ('from MD1 process_exception') print(exception) #------------------------------------------------------------------------- class MD2 (MiddlewareMixin): def process_request(self, request): # print(id(request)) print('from MD2 process_request') def process_response(self, request, response): # print(id(response)) print('from MD2 process_response') return response def process_view(self,request,view_func,view_args,view_kwargs): # print(view_func) # print(view_args) # print(view_kwargs) print('from MD2 process_view') def process_exception(self, request, exception): print('from MD2 process_exception') print(exception) # return HttpResponse('SSSSSS')
print(id(request))
print('from MD1 process_request')1
print('from MD1 process_response')6
print('from MD1 process_view')3
print ('from MD1 process_exception')
print('from MD2 process_request') 2
print('from MD2 process_response')5
print('from MD2 process_view')4
print('from MD2 process_exception')
print(exception)
############################
72452584
from MD1 process_request
from MD2 process_request
from MD1 process_view
from MD2 process_view
from MD2 process_response
from MD1 process_response
#除此之外还需在setting.py文件中进行注册 class LoginMD(MiddlewareMixin): white_lst = ['/login/',] #白名单 black_lst = ['/black/',] #黑名单 def process_request(self,request): return_url = request.path_info #黑名单限制访问 if return_url in self.black_lst: return HttpResponse('This is an illegal URL ') #白名单或者登录用户不做限制 elif return_url in self.white_lst or request.session.get('user'): return None else: return redirect('/login/?return_url={}'.format(return_url))