在 app 目录下创建 utils 目录,并在该目录下创建 throttle.py
throttle.py:
from rest_framework.throttling import BaseThrottle import time # 访问记录 VISIT_RECORD = {} class MyThrottle(BaseThrottle): """ 每 10 秒访问 3 次 """ def __init__(self): self.history = None # 用于记录访问记录 def allow_request(self, request, view): # 获取用户的 IP 地址 # 封装后的 request 中如果有的就不需要到 request._request 中找 remote_addr = request.get_ident(request) ctime = time.time() # 获取当前时间 # 如果 IP 还没记录,即第一次访问 if remote_addr not in VISIT_RECORD: # 记录第一次访问的 IP 地址和访问时间 VISIT_RECORD[remote_addr] = [ctime, ] return True # 获取访问记录 history = VISIT_RECORD.get(remote_addr) self.history = history # 把当前时间减 10 并和列表中最早的时间进行比较 while history and history[-1] < ctime - 10: history.pop() # 删除最早的一条记录 # 如果还没有 3 条记录 if len(history) < 3: # 将最新的访问时间插入到列表的第一个位置 history.insert(0, ctime) print(history) return True return False # 设置剩余访问时间的提示 def wait(self): ctime = time.time() return 10 - (ctime - self.history[-1])
history 列表的记录图示:
越早的访问记录放在列表的越后面的位置,方便操作
settings.py 中可以配置全局访问频率类:
REST_FRAMEWORK = { # 全局使用的访问频率类 "DEFAULT_THROTTLE_CLASSES": ["drf.utils.throttle.MyThrottle"], }
views.py:
from django.http import JsonResponse from rest_framework.views import APIView from drf.utils.throttle import MyThrottle ORDER_DICT = { 1: { "commodity": "Phone", "price": 3600, "date": "2021-01-03", }, 2: { "commodity": "Computer", "price": 6700, "date": "2021-01-05", }, } class OrderView(APIView): """ 查看订单 """ # 设置访问频率类 throttle_classes = [MyThrottle, ] def get(self, request, *args, **kwargs): response = {"code": 1000, "msg": None, "data": None} try: response["data"] = ORDER_DICT except Exception as e: pass return JsonResponse(response)
10 秒内前 3 次可正常访问,访问第 4 次: