13.Django之中间件
中间键的介绍
中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能
如果你想修改请求,例如被传送到view中的HttpRequest对象。 或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现
你还想在view执行之前做一些操作,这种情况就可以用 middleware来实现
中间键就在Django项目的Setting.py文件中,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', ]
Django的生命周期
自定义中间件
中间件可以定义为五个方法
- 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)
在request阶段按顺序从上到下穿过,而在response则反过来
自定义一个中间件
在自定义一个中间件,就要自己写一个类,但必须继承MiddlewareMixin函数
在项目下创建一个utils的包全局的
然后创建一个py文件名字随便 如middlewares.py
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class MD1(MiddlewareMixin): def process_request(self,request): print('MD1的process_request') def process_response(self,request,response): #request和response两个参数必须有 print('MD1的Process_response') # print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容 return response # return HttpResponse('ok') class MD2(MiddlewareMixin): def process_request(self,request): print('MD2的process_request') def process_response(self,request,response): print('MD2的Process_response') return response # return HttpResponse('ok')
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', 'utils.middlewares.MD1', #自定义中间件MD1,写的是路径 'utils.middlewares.MD2', #自定义中间件MD2 ]
打印的结果
Process_request
process_request有一个参数,就是request,这个request和视图函数的request是一样的
以上返回的值是None,则继续按照django定义的规则继续执行,如果是HttpResponse对象,则直接将该对象返回给用户
Process_response
它有两个参数,一个是request,一个是response,request就是上述例子中一样的对象,response是视图函数返回的HttpResponse对象。该方法的返回值也必须是HttpResponse对象
如果把自定义中间件的位置调换就会出现一下结果
流程图
process_view
process_view(self, request, view_func, view_args, view_kwargs)
该方法有四个参数
- request是HttpRequest对象。
- view_func是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)
- view_args是将传递给视图的位置参数的列表.
- view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)。
- Django会在调用视图函数之前调用process_view方法。
给DM1和DM2添加process_view
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class MD1(MiddlewareMixin): def process_request(self, request): print('MD1的process_request') def process_response(self, request, response): # request和response两个参数必须有 print('MD1的Process_response') # print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容 return response # return HttpResponse('ok') def process_view(selfself,request,view_func,view_args,view_kwargs): print('MD1的process_view') print(view_func,view_func.__name__) class MD2(MiddlewareMixin): def process_request(self, request): print('MD2的process_request') def process_response(self, request, response): print('MD2的Process_response') return response # return HttpResponse('ok') def process_view(selfself,request,view_func,view_args,view_kwargs): print('MD2的process_view') print(view_func,view_func.__name__)
返回结果
如果在MD1的process_view添加一个return HttpResponse('ok')返回的结果
执行的流程图
process_exception
process_exception(self,request,exception)
两个参数
- 一个是HttpRequest对象
- 另一个是exception是视图函数异常产生的Exception对象
只有在视图函数中出现异常才会执行
给DM1和DM2添加process_exception
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class MD1(MiddlewareMixin): def process_request(self, request): print('MD1的process_request') def process_response(self, request, response): # request和response两个参数必须有 print('MD1的Process_response') # print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容 return response # return HttpResponse('ok') def process_view(selfself,request,view_func,view_args,view_kwargs): print('MD1的process_view') print(view_func,view_func.__name__) # return HttpResponse('ok') def process_exception(self,request,exception): print(exception) print("MD1的process_exception") class MD2(MiddlewareMixin): def process_request(self, request): print('MD2的process_request') def process_response(self, request, response): print('MD2的Process_response') return response # return HttpResponse('ok') def process_view(selfself,request,view_func,view_args,view_kwargs): print('MD2的process_view') print(view_func,view_func.__name__) def process_exception(self,request,exception): print(exception) print("MD2的process_exception")
在login'页面添加个异常
raise ValueError()
运行结果
后面还有
MD2的Process_response
MD1的Process_response
如果在MD2中的Process_exception下加
return HttpResponse('ok')
运行结果为
流程图
process_template_response(很少用)
process_template_response(self,request,response)
它的参数,一个HttpRequest对象,response是TemplateResponse对象(由视图函数或者中间件产生)
process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class MD1(MiddlewareMixin): def process_request(self, request): print('MD1的process_request') def process_response(self, request, response): # request和response两个参数必须有 print('MD1的Process_response') # print(response.__dict__['_container'][0].decode('utf-8')) #查看响应体里面的内容 return response # return HttpResponse('ok') def process_view(selfself,request,view_func,view_args,view_kwargs): print('MD1的process_view') print(view_func,view_func.__name__) # return HttpResponse('ok') def process_exception(self,request,exception): print(exception) print("MD1的process_exception") 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') def process_response(self, request, response): print('MD2的Process_response') return response # return HttpResponse('ok') def process_view(selfself,request,view_func,view_args,view_kwargs): print('MD2的process_view') print(view_func,view_func.__name__) def process_exception(self,request,exception): print(exception) print("MD2的process_exception") def process_template_response(self,request,response): print("MD2的process_template_response") return response
views.py
def index(request): def render(): print("in index/render") return HttpResponse("O98K") rep = HttpResponse("OK") rep.render = render return rep
运行结果
视图函数执行完之后,立即执行了中间件的process_template_response方法,顺序是倒序,先执行MD1的,在执行MD2的,接着执行了视图函数返回的HttpResponse对象的render方法,返回了一个新的HttpResponse对象,接着执行中间件的process_response方法
Django请求流程