主要从SimpleRateThrottle的allow_request方法开始分析
第一步
1.查看SimpleRateThrottle的allow_request
if self.rate is None:
return True # 表示没有超过频率限制 可以访问
第二步
2.查看rate
def __init__(self):
if not getattr(self, 'rate', None): # 用了反射来获取rate 如果有则返回 没有返回None
self.rate = self.get_rate() # 由步骤4的推导得出 get_rate() 返回了'5/m'
self.num_requests, self.duration = self.parse_rate(self.rate) # 这里的(self.rate)就是5/m
# 解压赋值以后的num_requests是5,duration是60
自己写的频率类里面没有这个rate 所以返回None,那么继续走下面的代码
第三步
3.查看 self.rate = self.get_rate()这里的get_rate
还是在SimpleRateThrottle里面
if not getattr(self, 'scope', None):
# 反射了一个scope 这个就是我们自己写的定义在类里的属性
msg = ("You must set either `.scope` or `.rate` for '%s' throttle" %
self.__class__.__name__)
raise ImproperlyConfigured(msg)
try:
return self.THROTTLE_RATES[self.scope]
except KeyError:
msg = "No default throttle rate set for '%s' scope" % self.scope
raise ImproperlyConfigured(msg)
# 如果不写scope的话就会抛异常
有的话就执行 return self.THROTTLE_RATES[self.scope]
第四步
4.查看 THROTTLE_RATES[self.scope]
THROTTLE_RATES = api_settings.DEFAULT_THROTTLE_RATES
这个是按照scope键去我们配置的文件字典取值里取V值
'throttling': '5/m' throttling就是我们自定义的scope的名字
第五步
5.查看parse_rate
def parse_rate(self, rate):
if rate is None: # 如果rate没有值则返回none
return (None, None)
num, period = rate.split('/') # 有的话按斜杠切割一下 变成这种形式['5','m']
num_requests = int(num) # 把'5' 变成数字
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]] # 此时的period[0]就是m
return (num_requests, duration) 返回的就是 5,60
第六步
6.回到SimpleRateThrottle的allow_request的第二段代码
第一段就是我们第一步查看的 以上就是它的rate里面值的查找过程
现在的rate是有值的 那么会继续走下面的代码
self.key = self.get_cache_key(request, view) # 此时的self.get_cache_key就是我们继承以后重写的方法
if self.key is None: # key是我们以重写的以什么作为频率限制的返回值 自己是返回的IP
return True
第七步
7.有值的话代码继续往下走
self.history = self.cache.get(self.key, []) # self.history访问者的时间列表 从缓存中获取
# 如果有时间的话就是 ip[时间1,时间2] ,没有的话就是空列表ip[]
self.now = self.timer()
# 获取了当前时间
第八步
8.判断访问的频率
while self.history and self.history[-1] <= self.now - self.duration:
# 循环访问者的时间列表,如果时间列表的最后一位小于或者等于当前时间减去60
self.history.pop() #就将它移除掉
if len(self.history) >= self.num_requests: # 判断时间类表的长度是否大于或者等于之前列表配置的次数
return self.throttle_failure() # throttle_failure()返回值是false 大于就限制了访问
return self.throttle_success()
第九步
9. 第八步如果访问次数没有超出配置的次数 那么返回下面代码的内容
def throttle_success(self):
self.history.insert(0, self.now) # 将当前时间插入到访问时间列表的第一位
self.cache.set(self.key, self.history, self.duration)
#将访问者的ip,时间列表,访问频率的时间 存放在缓存中 方便下次取数据
return True
总结
'''总结 : 以后写频率类的时候继承SimpleRateThrottle
重写 get_cache_key方法 一定要写一个类属性 scope 配置文件一定要写
'''
标签:None,return,get,self,rate,源码,scope,三大,drf
From: https://www.cnblogs.com/Hsummer/p/16779435.html