Django-中间件-middleware
中间件:
中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。
每个中间件都会负责一个功能,例如,AuthenticationMiddleware,与sessions处理相关。
适用于对所有请求以及部分内容做批量处理,例如缓存、
配置中间件
在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件。
settings.py
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.middleware.clickjacking.XFrameOptionsMiddleware
浏览器访问的过程是发送request请求,然后返回一个response, 这个请求传递到 Django的过程如下:
每一个中间件都是一个类,而当客户端对服务器发送请求的时候,首先会顺序执行中间件list中的每一个元素中的process_request函数,最后通过路由系统执行请求url所对应的view中的function,执行完成后会返回一个response,然后再从中间件列表中的最后一个元素的process_response开始,依次往上执行每一个元素中的process_response。
而我们也可以在中间件列表中添加我们自定义的中间件
自定义中间件:
1、创建中间件类:
from django.utils.deprecation import MiddlewareMixin class M1(MiddlewareMixin): def process_request(self,request): 当process_request中有返回值的时候,会直接从自身的process_response依次向上执行 print('m1.process_request') def process_view(self,request,callback,callback_args,callback_kwargs): 当process_view函数中有返回的时候,会从中间件列表的最后一个元素的process_response函数依次向上执行 print('m1.process_view') response=callback(request,*callback_args,**callback_kwargs) return response def process_response(self,request,response): print("m1.process_response") return response class M2(MiddlewareMixin): def process_request(self,request): print('m2.process_request') def process_view(self,request,callback,callback_args,callback_kwargs): print('m2.process_view') def process_respones(self,request,response): print('m2.process_response') return response
2、注册中间件:
from django.middleware.common import CommonMiddleware 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', 'md.M1', 'md.M2', ]
3、views.py
from django.shortcuts import render,HttpResponse,redirect
def test (request): print("test") return HttpResponse("...")
4、访问执行结果:
m1.process_request m2.process_request m1.process_view test m2.process_response
m1.process_response
process_exception
当views的函数中出现错误时,就会从中间件列表中的最后一个元素的process_exception方法开始执行,然后依次向上执行,直到执行到第一个的process_exception方法后,再从中间件列表中最后一个元素的process_response开始依次向上返回,顺序如上图所示。
如果在process_exception方法中有返回的话,则会停止向上执行 process_exception立刻从中间件列表中的最后一个元素的process_response依次向上返回。
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'Fade Zhao' from django.utils.deprecation import MiddlewareMixin class M1(MiddlewareMixin): def process_request(self,request): print('m1.process_request') def process_view(self,request,callback,callback_args,callback_kwargs): print('m1.process_view') def process_response(self,request,response): print("m1.process_response") return response def process_exception(self,request,exception): #没有添加返回 print('M1.process_exception') class M2(MiddlewareMixin): def process_request(self,request): print('m2.process_request') def process_view(self,request,callback,callback_args,callback_kwargs): print('m2.process_view') def process_response(self,request,response): print('m2.process_response') return response def process_exception(self,request,exception): print('M2.process_exception')
views.py
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'Fade Zhao' from django.shortcuts import render,HttpResponse,redirect def test (request): print("test") int('asdf') #这导致报错 return HttpResponse("........")
输出:
m1.process_request m2.process_request m1.process_view m2.process_view test M2.process_exception M1.process_exception Internal Server Error: /Family/test.html Traceback (most recent call last): .......报错信息...... m2.process_response m1.process_response
在process_exception中添加返回值:
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'Fade Zhao' from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render,HttpResponse,redirect class M1(MiddlewareMixin): def process_request(self,request): print('m1.process_request') def process_view(self,request,callback,callback_args,callback_kwargs): print('m1.process_view') def process_response(self,request,response): print("m1.process_response") return response def process_exception(self,request,exception): print('M1.process_exception') return HttpResponse('出错了') #在函数中添加返回 class M2(MiddlewareMixin): def process_request(self,request): print('m2.process_request') def process_view(self,request,callback,callback_args,callback_kwargs): print('m2.process_view') def process_response(self,request,response): print('m2.process_response') return response def process_exception(self,request,exception): print('M2.process_exception') return HttpResponse('出错了') #添加返回
同样的views.py,访问后输出:
m1.process_request
m2.process_request
m1.process_view
m2.process_view
test
M2.process_exception
m2.process_response
m1.process_response
process_template_response:
process_template_response正常执行的话是不会调用,只有views函数的返回值对象中,如果有render()方法,这个函数才会被调用,
调用顺序和是先调用是
views.function-->M2.process_template_response-->M1.process_template_response-->Foo.render-->M2.process_response-->M2.process_response
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'Fade Zhao' from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render,HttpResponse,redirect class M1(MiddlewareMixin): def process_request(self,request): print('m1.process_request') def process_view(self,request,callback,callback_args,callback_kwargs): print('m1.process_view') def process_response(self,request,response): print("m1.process_response") return response def process_exception(self,request,exception): print('M1.process_exception',exception) return HttpResponse('出错了') def process_template_response(self,requset,response): print('M1.process_template_response') return response class M2(MiddlewareMixin): def process_request(self,request): print('m2.process_request') def process_view(self,request,callback,callback_args,callback_kwargs): print('m2.process_view') def process_response(self,request,response): print('m2.process_response') return response def process_exception(self,request,exception): print('M2.process_exception',exception) return HttpResponse('出错了') def process_template_response(self,requset,response): ''' 视图函数的返回值对象中,如果有render方法,这个函数才会被调用 ''' print('M2.process_template_response') return response
views.py
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = 'Fade Zhao' from django.shortcuts import render,HttpResponse,redirect import json class Foo: def __init__(self, request, status, msg): self.request = request self.status = status self.msg = msg def render(self): #在依次向上执行process_template_response后执行此函数 print('Foo.render') ret = { 'status': self.status, 'msg': self.msg } ret = json.dumps(ret) return HttpResponse(ret) def test (request): print("test") obj = Foo(request,True,'欢迎新同学') # 主要应用场景是在处理Ajax请求时,当做模板来使用 return obj
输出:
m1.process_request
m2.process_request
m1.process_view
m2.process_view
test
M2.process_template_response
M1.process_template_response
Foo.render
m2.process_response
m1.process_response