概念

是一个轻量级的,底层的插件,可以介入Django的请求和相应过程(面向切面编程)

中间件的本质就是一个python类

详细介绍请看:https://segmentfault.com/a/1190000019992887

MCS结构体系

8NIoOH.png

面向切面编程

简称AOP(Aspect Oriented Programming)。AOP的主要实现目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合的隔离效果。

中间件的可切入点

1NjpFI.png

切入函数

  • __init__:没有参数,服务器响应第一个请求的时候自动调用,用户确定是否启用该中间件
  • process_request(self,request):在执行视图前被调用,每个请求上都会调用,不主动进行返回或返回HttpResponse对象
  • process_view(self,request,view_func,view_args,view_kwargs):调用视图之前执行,每个请求都会调用,不主动进行返回或返回HttpResponse对象
  • process_template_response(self,request,response):在视图刚好执行完后进行调用,每个请求都会调用,不主动进行返回或返回HttpResponse对象
  • process_response(self,request,response):所有响应返回浏览器之前调用,每个请求都会调用,不主动进行返回或返回HttpResponse对象

自定义中间件

process_exception(self,request,exception):当视图抛出异常时调用,不主动进行返回或返回HttpResponse对象

自定义中间件流程

  1. 在工程目录下创建middleware目录

  2. 目录中创建一个python文件

  3. 在python文件中导入中间件的基类

    from django.utils.deprecation import MiddlewareMixin

  4. 在类中根据功能需求,创建切入需求类,重写切入点方法

    1
    2
    3
    class LearnAOP(MiddlewareMixin):
    def process_request(self,request):
    print('request的路径',request.GET.path)
  5. 启用中间件,在settings中进行配置,MIDDLEWARE中添加

    middleware.文件名.类名

注意:在django2.2官方推荐的文档里,一般这样写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Md1:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# 在这里编写视图和后面的中间件被调用之前需要执行的代码
# 这里其实就是旧的process_request()方法的代码
response = self.get_response(request)
# 在这里编写视图调用后需要执行的代码
# 这里其实就是旧的process_response()方法的代码
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print("Md1在执行%s视图前")
def process_exception(self,request,exception):
print("Md1处理视图异常")

实例1 ip拦截

1
2
3
4
5
6
7
8
class BlackListMiddleware():
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.META['REMOTE_ADDR'] in getattr(settings, "BLACKLIST", []):
return HttpResponseForbidden('<h1>该IP地址被限制访问!</h1>')
response = self.get_response(request)
return response

实例2 频率反爬

8NoFkq.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Md1:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
black_list = cache.get('black',[])
if ip in black list:
return HttpResponse("黑名单用户,凉凉")
requests = cache.get(ip, [])
while requests and time.time().requests[-1] > 60:
requests.pop()
requests.insert(0,time.time())
cache.set(ip, requests, timeout=60)
if len(requests) > 30:
black_list.append(ip)
cache.set('black', black list, timeout=60*60*24)
return HttpResponse("小爬虫小黑屋里呆着吧")
if len(requests) > 10:
return HttpResponse("请求次数过于频繁,小爬虫回家睡觉吧")
response = self.get_response(request)
return response

CSRF豁免

在views函数前加装饰器@csrf_exempt

思维导图

8N5kbn.png