Django 详解 中间件Middleware
Django中间件
还是涉及到django的请求生命周期。middle ware 请求穿过中间件到达url,再经过中间件返回给用户。
简单实例
django项目根目录新建一个Middle文件夹,再新建一个test.py文件
在test文件中写入;其中的类必须继承 from django.utils.deprecation import MiddlewareMixin
from django.utils.deprecation import MiddlewareMixin class M1(MiddlewareMixin): def process_request(self, request): print('m1') def process_response(self, request, response): print('m1_r') return response class M2(MiddlewareMixin): def process_request(self, request): print('m2') def process_response(self, request, response): print('m2_r') return response class M3(MiddlewareMixin): def process_request(self, request): print('m3') def process_response(self, request, response): print('m3_r') return response
将你的测试中间件加入Django的中间件配置中,settings文件
随便建一组对应路由。
在index函数里面写上
def index(request): print('到达') return HttpResponse('ok')
查看结果:
此时如果给某个中间件的process_request返回一个HttpResponse:
#!/user/bin/env python # -*-coding: utf-8-*- from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class M1(MiddlewareMixin): def process_request(self, request): print('m1') def process_response(self, request, response): print('m1_r') return response class M2(MiddlewareMixin): def process_request(self, request): print('m2') return HttpResponse('中断') # 这里返回 def process_response(self, request, response): print('m2_r') return response class M3(MiddlewareMixin): def process_request(self, request): print('m3') def process_response(self, request, response): print('m3_r') return response
查看下结果
可能你好像懂了,但是并没有,真正的中间件过程其实还有一个process_view.
自定制中间件的另一种方式
下面是最新的django2.1文档内的自定制中间件的另一种写法。
一个中间件工厂是可以被调用的,它接收一个可调用的get_response方法并返回一个中间件。中间件也是可调用的,它接收请求并返回响应,就像一个view视图
def simple_middleware(get_response): # 一次性配置和初始化 def middleware(request): # 在每个请求之前被执行的代码 #这个视图(和后面的中间件)被调用 response = get_response(request) # 在每个请求或者响应之后代码被执行 # the view is called. return response return middleware
或者他也可以被重写成一个实例可以被调用的类,像这个:
class SimpleMiddleware: def __init__(self, get_response): self.get_response = get_response # 一次性配置和初始化 def __call__(self, request): # 在每一次请求之前代码被执行 # 视图或者接下来的中间件被调用 response = self.get_response(request) # 在每个请求或者响应之后代码将会被执行 # the view is called. return response
可调用的get_response是由django提供的,可以是真实的视图函数或者也可以是链上的下一个中间件。当前的中间件不需要具体精确地知道或者关心它是什么,只是它代表接下来执行(到来的)是什么。
上面是一个小小的简化,可调用的get_response如果在中间件的最后一位,将不会是一个真实的视图函数,更可能是处理的一个外部包装方法,它关注于应用视图中间件,调用视图和合适的URL参数,并且使用template和exception中间件.
中间件可以生存在你的Python路径的任何地方。
__init__(get_response)
中间件工厂必须接收一个get_response参数,你也可以为中间件初始化一些全局的状态。记住下面的这几点
1、django只能使用get_response参数来初始化你的中间件,所以你不能定义__init__()来需要其他的参数
2、跟__call__()方法每次请求被调用不同,__init__()方法只会被调用一次,当web服务启动的时候
例如
class LoginMiddleware: def __init__(self, get_response): self.get_response = get_response @method_decorator(adminlogin) def __call__(self, request): if request.method == "PUT": request.data = dict(urllib.parse.parse_qsl(request.body.decode())) request.data.update(request.GET.dict()) elif request.method == "POST": request.data = request.POST.copy().dict() response = self.get_response(request) return response
1 def performance(func): 2 def wrapper(request): 3 mark1 = time.time() 4 start = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(mark1)) # 2018-09-28 03:42:08 5 response = func(request) 6 if response.status_code == 200 and request.path.split('/')[1] == 'api': # api url& response success 7 mark2 = time.time() 8 cost = mark2 - mark1 9 end = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(mark2)) 10 note = 'url: %s |%s | total cost: %s | start time: %s | end time: %s\r\n' % (request.path, request.GET, cost, start, end) 11 12 with open(performance_file, 'a+') as obj: 13 obj.write(note) 14 return response 15 return wrapper 16 17 18 class PerformanceMiddleware: 19 def __init__(self, get_response): 20 self.get_response = get_response 21 22 @method_decorator(performance) 23 def __call__(self, request): 24 response = self.get_response(request) 25 return response
详情请查阅django(version2.1)文档:https://docs.djangoproject.com/en/2.1/topics/http/middleware/