自定义频率类
1 频率类
2 视图类
3 路由
4 频率源码分析
1 频率类
'''
# 写限制逻辑
(1)取出访问者ip
(2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
(3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
(4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,
返回True,顺利通过
(5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
return False
频率类写好,配置在视图类上,就会走它
'''
class MyThrottle(BaseThrottle):
VISIT_RECORD = {}
def __init__(self):
self.history = []
def allow_request(self, request, view):
ip = request.META.get('REMOTE_ADDR')
import time
ctime = time.time()
if ip not in self.VISIT_RECORD:
self.VISIT_RECORD[ip] = [ctime, ]
return True
self.history = self.VISIT_RECORD[ip]
while self.history and ctime - self.history[-1] > 60:
self.history.pop()
if len(self.history) < 3:
self.history.insert(0, ctime)
return True
return False
def wait(self):
import time
ctime = time.time()
return 60 - (ctime - self.history[-1])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
2 视图类类
from rest_framework.viewsets import GenericViewSet
from .throttling import MyThrottle
class BookView(GenericViewSet):
throttle_classes = [MyThrottle]
def list(self, request):
print(self.request)
return Response('测试自定义频率')
3 路由
from django.contrib import admin
from django.urls import path
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('books', BookView, 'books')
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns += router.urls
-APIView----disaptch---》self.initial(request, *args, **kwargs)---》416行:self.check_throttles(request)----》352行 check_throttles
def check_throttles(self, request):
for throttle in self.get_throttles():
if not throttle.allow_request(request, self):
throttle_durations.append(throttle.wait())
1 写一个类,继承,BaseThrottle
2 在类中重写:allow_request方法,传入 3个参数
3 在allow_request写限制逻辑,如果还能访问--》返回True
4 如果超了次数,就不能访问,返回False
5 局部配置在视图类上
6 全局配置在配置文件中
-我们猜测:一定是 SimpleRateThrottle帮咱们写了咱们需要写的
(1)取出访问者ip
(2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
(3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
(4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
(5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
- SimpleRateThrottle内部一定有:allow_request---》
def allow_request(self, request, view):
if self.rate is None:
return True
self.key = self.get_cache_key(request, view)
if self.key is None:
return True
self.history = self.cache.get(self.key, [])
self.now = self.timer()
while self.history and self.history[-1] <= self.now - self.duration:
self.history.pop()
if len(self.history) >= self.num_requests:
return self.throttle_failure()
return self.throttle_success()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56