源码相关: # 1)APIView的dispath方法中的 self.initial(request, *args, **kwargs) 点进去 # 2)self.check_throttles(request) 进行频率认证 # 频率组件核心源码分析 def check_throttles(self, request): throttle_durations = [] # 1)遍历配置的频率认证类,初始化得到一个个频率认证类对象(会调用频率认证类的 __init__() 方法) # 2)频率认证类对象调用 allow_request 方法,判断是否限次(没有限次可访问,限次不可访问) # 3)频率认证类对象在限次后,调用 wait 方法,获取还需等待多长时间可以进行下一次访问 # 注:频率认证类都是继承 SimpleRateThrottle 类 for throttle in self.get_throttles(): if not throttle.allow_request(request, self): # 只要频率限制了,allow_request 返回False了,才会调用wait throttle_durations.append(throttle.wait()) if throttle_durations: # Filter out `None` values which may happen in case of config / rate # changes, see #1438 durations = [ duration for duration in throttle_durations if duration is not None ] duration = max(durations, default=None) self.throttled(request, duration)
1 自定义频率类: 2 3 指路实现: 4 5 1) 自定义一个继承 SimpleRateThrottle 类 的频率类 6 2) 设置一个 scope 类属性,属性值为任意见名知意的字符串 7 3) 在settings配置文件中,配置drf的DEFAULT_THROTTLE_RATES,格式为 {scope字符串: '次数/时间'} 8 4) 在自定义频率类中重写 get_cache_key 方法 9 # 限制的对象返回 与限制信息有关的字符串 10 # 不限制的对象返回 None (只能放回None,不能是False或是''等) 11 12 eg:短信接口 1/min 频率限制 13 14 from rest_framework.throttling import SimpleRateThrottle 15 16 class SMSRateThrottle(SimpleRateThrottle): 17 scope = 'sms' 18 19 # 只对提交手机号的get方法进行限制 20 def get_cache_key(self, request, view): 21 mobile = request.query_params.get('mobile') 22 # 没有手机号,就不做频率限制 23 if not mobile: 24 return None 25 # 返回可以根据手机号动态变化,且不易重复的字符串,作为操作缓存的key 26 return 'throttle_%(scope)s_%(ident)s' % {'scope': self.scope, 'ident': mobile} 27 28 29 30 drf配置 31 REST_FRAMEWORK = { 32 # 频率限制条件配置 33 'DEFAULT_THROTTLE_RATES': { 34 'sms': '1/min' 35 }, 36 } 37 38 views 39 from .throttles import SMSRateThrottle 40 class TestSMSAPIView(APIView): 41 # 局部配置频率认证 42 throttle_classes = [SMSRateThrottle] 43 def get(self, request, *args, **kwargs): 44 return APIResponse(0, 'get 获取验证码 OK') 45 def post(self, request, *args, **kwargs): 46 return APIResponse(0, 'post 获取验证码 OK') 47 48 路由配置 49 url(r'^sms/$', views.TestSMSAPIView.as_view()),