源码相关:
# 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()),