赞
踩
以下图是客户端发起一次http请求的流程:
注意:django框架不包括socket,要借助图中两个模块实现socket,进行客户端和服务器通信。wsgi性能较弱,一般测试开发用;企业中用uwsgi比较好,性能强,并发好
。
上图可知,在请求到达视图之前,会依次执行中间件,视图返回的响应,依次倒序执行中间件
。
django 中间件(middleware),在django中其实就是一个类
,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。
在django项目的setting.py文件中,有一个MIDDLEWARE列表,其中每一个元素都是一个中间件
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'qinspect.middleware.QueryInspectMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
若需要对请求作统一处理,比如执行,验证登录、日志记录、获取CBV响应时间,我们可以使用装饰器,但是很麻烦,每个视图都要手动加装饰器,这时使用中间件会更方便。
1.做IP限制:
2.URL访问过滤:
3.缓存:
下面我们自定义一个中间件,获取每个接口响应时间:
#!/usr/bin/python # -*- coding: utf-8 -*- from __future__ import unicode_literals, print_function import time from django.utils.deprecation import MiddlewareMixin from libs.api_tools import slow_api_utils class CustomizeMiddleware(MiddlewareMixin): """自定义中间件: 获取所有接口的处理时间.""" def process_request(self, request): # 获取这个请求的开始时间 self.start_time = time.time() def process_response(self, request, response): end_time = time.time() # 结束时间 - request 开始时间 = 接口的处理时间 process_time = end_time - self.start_time # 下面是处理process_time 时间发起异步请求, 这里省略...... slow_api_utils.judge_max_process_time(request, process_time) return response
在setting.py中注册中间件:
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'qinspect.middleware.QueryInspectMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'libs.api_tools.middleware.CustomizeMiddleware' # 创建的自定义中间件类(路径 + 类名)
]
注意:django 1.10之后django无法导入,因此直接把MiddlewareMixin类拿过来继承就好了:
class MiddlewareMixin(object): def __init__(self, get_response=None): self.get_response = get_response super(MiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): response = self.process_request(request) if not response: response = self.get_response(request) if hasattr(self, 'process_response'): response = self.process_response(request, response) return response class CustomizeMiddleware(MiddlewareMixin): # 自定义类,继承MiddlewareMixin ......
同样也是在setting.py中注册中间件:
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'qinspect.middleware.QueryInspectMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'libs.api_tools.middleware.CustomizeMiddleware' # 创建的自定义中间件类(路径 + 类名)
]
process_request 请求进来时执行;
不能有返回值,若在process_request有返回值,那么下面的中间件将不会执行,后面的URL以及视图函数也不会执行,直接执行当前的中间件的process_response方法。
# 请求时,仅让IP为192.168.1.1才可以进行访问
from django.shortcuts import HttpResponse
class CustomizeMiddleware(MiddlewareMixin):
def process_request(self, request, response):
allowed_ip = ['192.168.1.1',]
# 允许/禁止访问的ip地址列表,判断请求ip, 放行/阻拦
if request.META.get('REMOTE_ADDR') not in allowed_ip:
return HttpResponse('您的IP地址无权访问')
else:
return None
def process_response(self, request, response):
return response
process_response 返回响应时执行;
默认情况下返回response, 即视图函数的返回值,如果在这个方法中自定义了返回值,将返回自定义返回值。
class CustomizeMiddleware(MiddlewareMixin):
def process_response(self, request, response):
print('处理一些逻辑条件等......')
return response
process_view 视图函数;
执行过程:
执行完process_request → 路由分发(dispatch) → process_view → 视图函数 → process_response
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class CustomizeMiddleware1(MiddlewareMixin): def process_request(self,request): print("...来自中间件1的请求...") def process_response(self,request,response): print("...来自中间件1的返回...") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("...中间件1view...") class CustomizeMiddleware2(MiddlewareMixin): def process_request(self,request): print("...来自中间件2的请求...") def process_response(self,request,response): print("...来自中间件2的返回...") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("...中间件2view...") class CustomizeMiddleware3(MiddlewareMixin): def process_request(self,request): print("...来自中间件3的请求...") def process_response(self,request,response): print("...来自中间件2的返回...") return response def process_view(self, request, callback, callback_args, callback_kwargs): print("...中间件3view...")
# 输出结果为:
...来自中间件1的请求..
...来自中间件2的请求..
...来自中间件3的请求..
...中间件1view...
...中间件2view...
...中间件3view...
...来自中间件3的返回...
...来自中间件2的返回...
...来自中间件1的返回...
如图所示:
当最后一个中间的process_request到达路由关系映射之后,返回到中间件1的process_view,然后依次往下,到达views函数,最后通过process_response依次返回到达用户。
process_exception 视图中出现异常,就会被执行(默认不执行);
# 定义一个提示错误信息页面
from django.shortcuts import HttpResponse
class CustomizeMiddleware(MiddlewareMixin):
def process_exception(self, request, exception):
return HttpResponse('在处理中间件时,抛出了异常,就会走这里哦~')
process_template_response 若返回的对象有render方法,就会被执行(默认不执行);
process_template_response(self, request, response)
视图函数执行完成后立即执行
,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法
(或者表明该对象是一个TemplateResponse对象或等价方法)Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。