控制用户的访问频率,比如一分钟内某一个用户只允许访问三次,我们就需要用到频率组件
自定义用户访问频率组件的逻辑:
1.定义一个用户访问的字典,用户访问时取出他ip 2.判断ip在不在字典里,不在就添加进去并返回True,表示第一次访问 3.循环判断当前ip的列表,列表里有值的话就用当前的时间减去列表的最后一个时间,大于60s就把这个数据pop掉,这样列表中只有60s之内的访问时间了 4.判断列表是否小于3,小于3表示一分钟内访问的不足三次,把当前时间插入到列表的第一个位置,返回True并顺利通过 5.当大于3说明一分钟内访问超过三次,返回False验证失败
代码实现:
class MyThrottles(): VISIT_RECORD = {} def __init__(self): self.history=None def allow_request(self,request, view): # 取出访问者ip # print(request.META) ip=request.META.get('REMOTE_ADDR') import time ctime=time.time() # 判断当前ip在不在字典里,不在就添加进去并返回True,表示第一次访问 if ip not in self.VISIT_RECORD: self.VISIT_RECORD[ip]=[ctime,] return True self.history=self.VISIT_RECORD.get(ip) # 循环判断当前ip的列表,有值的话就用当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间, while self.history and ctime-self.history[-1]>60: self.history.pop() # 判断列表是否小于3,小于则说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过 # 当大于等于3,说明一分钟内访问超过三次,返回False验证失败 if len(self.history)<3: self.history.insert(0,ctime) return True else: return False def wait(self): import time ctime=time.time() return 60-(ctime-self.history[-1])
限制频率的局部使用
# 写一个类,继承自SimpleRateThrottle,(根据ip限制) from rest_framework.throttling import SimpleRateThrottle class VisitThrottle(SimpleRateThrottle): scope = 'restrict' def get_cache_key(self, request, view): return self.get_ident(request)
# 在setting里配置:(一分钟访问三次) REST_FRAMEWORK = { 'DEFAULT_THROTTLE_RATES':{ 'restrict':'3/m' } }
# 在视图类里使用 throttle_classes = [MyThrottles,]
用户限制次数的中文提示:
class Course(APIView): throttle_classes = [MyThrottles,] def get(self, request): return HttpResponse('get') def post(self, request): return HttpResponse('post') def throttled(self, request, wait): from rest_framework.exceptions import Throttled class MyThrottled(Throttled): default_detail = '稍后重试' extra_detail_singular = '还有 {wait} second.' extra_detail_plural = '出了 {wait} seconds.' raise MyThrottled(wait)
全局使用:
REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES':['app01.utils.VisitThrottle',], 'DEFAULT_THROTTLE_RATES':{ 'restrict':'3/m' } }