整理了几个版本的,经过测试目前正常.....
第一版:
第一版和第三版引用方式不同,第三版是在视图类里面,第一版是在配置文件引用.
REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES': ( 'throttle.service.throttle_class.VisitThrottle', ), }
第二版:
#!/usr/bin/env python # -*- coding:utf-8 -*- # Python import time # Third-party Library from rest_framework.throttling import BaseThrottle from rest_framework import exceptions class MyException(exceptions.Throttled): default_detail = "你的访问次数超限,请稍后在访问..." extra_detail_plural = extra_detail_singular = '请在{wait}秒内访问' def __init__(self, wait=None, detail=None, code=None): super().__init__(wait=wait, detail=detail, code=code) # 访问记录 VISITED_RECORD = {} class VisitThrottle(BaseThrottle): def __init__(self): self.history = None self.ctime = time.time() self.period = 60 self.visit_ip = None # 访问限制方法 def allow_request(self, request, view): visit_ip = self.get_ident(request) self.visit_ip = visit_ip # visit_ip=request.META.get('REMOTE_ADDR') print(visit_ip) # 第一次访问请求 if visit_ip not in VISITED_RECORD: VISITED_RECORD[visit_ip] = [self.ctime] return True # self.history:当前请求IP的记录列表 self.history = VISITED_RECORD[visit_ip] print(self.history) # 第2,3,...次访问请求 if len(VISITED_RECORD[visit_ip]) < 3: VISITED_RECORD[visit_ip].insert(0, self.ctime) return True if self.ctime - VISITED_RECORD[visit_ip][-1] > self.period: VISITED_RECORD[visit_ip].pop() VISITED_RECORD[visit_ip].insert(0, self.ctime) return True view.throttled = self.throttled return False def wait(self): return self.ctime - VISITED_RECORD[self.visit_ip][-1] def throttled(self, request, wait): raise MyException(wait=wait)
第三版:
#!/usr/bin/env python # -*- coding:utf-8 -*- """ 功能:限制用户访问频率 """ # Django Library import time, math # Third-party Library from rest_framework import exceptions class MyException(exceptions.Throttled): default_detail = '连接次数过多...' extra_detail_plural = extra_detail_singular = '请在{wait}秒内访问' def __init__(self, wait=None, detail=None, code=None): super().__init__(wait=wait, detail=detail, code=code) class VisitThrottle(): user_visit_information = dict() visited_times = 1 period = 60 allow_times_per_minute = 5 first_time_visit = True def allow_request(self, request, view): self.request_host = request_host = request.META.get("REMOTE_ADDR") current_user_info = self.user_visit_information.get(request_host, None) if not self.__class__.first_time_visit: self.user_visit_information[request_host][0] += 1 current_visit_times = self.user_visit_information[request_host][0] if current_visit_times > self.allow_times_per_minute: if self._current_time - current_user_info[1] <= self.period: if len(current_user_info) > 2: current_user_info[2] = self._time_left else: current_user_info.append(self._time_left) view.throttled = self.throttled return None else: self.__class__.first_time_visit = True if self.first_time_visit: self.__class__.first_time_visit = False self._initial_infomation() return True def wait(self): return self.period - self.user_visit_information[self.request_host][2] def throttled(self, request, wait): raise MyException(wait=wait) @property def _current_time(self): return time.time() @property def _time_left(self): return math.floor(self._current_time - self.user_visit_information.get(self.request_host)[1]) def _initial_infomation(self): self.user_visit_information[self.request_host] = [self.visited_times, self._current_time]
如何使用上面的代码限制频率
打开你的视图文件,一般是views.py,如果你把文件修改名字了,那么就放在你修改你后的文件里.
# 导入频率组件,也就是上面的文件 from app01.service.throttle import VisitThrottle # 图书视图类 class BookView(ModelViewSet): # 频率限制 throttle_classes = [VisitThrottle] # 获取图书列表 queryset = Book.objects.all() # 序列化类 serializer_class = BookSerializer ''' 注意: 因为之前写过认证组件和权限组件了,这里只写和频率认证组件有关的代码,就不重复粘代码. 可以去上一篇把代码粘过来. https://www.cnblogs.com/apollo1616/articles/10100264.html '''