频率组件源码:
APIView的initial方法:(执行APIView的as_view方法,执行APIView的dispatch方法,执行APIView的initial方法)
APIView的check_throttles方法
跟认证组件和权限组件一样。throttle是配置的每个频率控制类的实例化对象,配置文件中的"DEFAULT_THROTTLE_CLASSES"
并且每个频率控制类都有allow_request和wait方法
把所有频率组件走一遍,然后把等待时间最长的作为异常抛出
APIView的throttled方法,抛出异常
自己实现的频率控制类:
在项目目录下创建utils目录,创建throttle.py
from rest_framework.throttling import BaseThrottle import time VISIT_RECORD = {} # 访问列表 class MyThrottle(BaseThrottle): def __init__(self): self.history = None def allow_request(self, request, view): # 实现限流的逻辑 # 以IP地址限流 # IP地址的访问列表 {IP:[time1, time2, time3]} # 1. 获取请求的IP地址 ip = request.META.get("REMOTE_ADDR") # 2. 判断IP地址是否在访问列表 # --1 不在,需要给访问列表添加key value now = time.time() if ip not in VISIT_RECORD: VISIT_RECORD[ip] = [now, ] return True # --2 在,需要把这个IP的访问记录 把当前时间加入到列表头部(也可以是尾部) history = VISIT_RECORD[ip] history.insert(0, now) # 3. 确保列表里最新访问时间以及最老的访问时间差 是1分钟(假如限制时间是1分钟) while history and history[0] - history[-1] > 60: # 执行完该循环,列表里的时间都是一分钟之内的了 history.pop() self.history = history # 4. 得到列表长度,判断是否是允许的次数(假设允许1分钟最多3次) if len(history) > 3: return False else: return True def wait(self): # 返回需要等待的时间 wait_time = 60 - (self.history[0] - self.history[-1]) return wait_time
在视图中使用:
from utils.throttle import MyThrottle class DemoView(APIView): throttle_classes = [MyThrottle, ] def get(self, request): return Response("测试限流类")
框架自带的限流类用法(跟我们自己实现的同样功能,每分钟限制3次):
配置settings: