SimpleRateThrottle这个类写的其实挺完整了,我们继承他适当配置下就可以了
def allow_request(self, request, view): """ Implement the check to see if the request should be throttled. On success calls `throttle_success`. On failure calls `throttle_failure`. """ if self.rate is None: return True self.key = self.get_cache_key(request, view)# 这里跟进去看了没写,需要我们自定义一个key if self.key is None: return True self.history = self.cache.get(self.key, []) #这里跟进去看了cache。get获取的是django的缓存,也就是,取django缓存中找我们需要的kye。 self.now = self.timer() #获取当前时间戳,跟进去看过 # Drop any requests from the history which have now passed the # throttle duration while self.history and self.history[-1] <= self.now - self.duration: self.history.pop() if len(self.history) >= self.num_requests: #如果我们保持的列表成员数大于设置好的频次。这个num_requests上一篇讲过失去配置文件找我们是自定义了 return self.throttle_failure() #返回False return self.throttle_success() #insert后返回True def throttle_success(self): """ Inserts the current request's timestamp along with the key into the cache. """ self.history.insert(0, self.now) self.cache.set(self.key, self.history, self.duration) return True def throttle_failure(self): """ Called when a request to the API has failed due to throttling. """ return False
通过分析上面代码,发现我们需要一个kye,保存到系统缓存。如果全部用内置的方法,那么self.duration和self.num_requests我们用内置的方法。
看下获取这个这两个参数的位置:
def __init__(self): if not getattr(self, 'rate', None): self.rate = self.get_rate() self.num_requests, self.duration = self.parse_rate(self.rate)#传入上面的参数
self.get_rate()方法内部
def get_rate(self): """ Determine the string representation of the allowed request rate. """ if not getattr(self, 'scope', None): msg = ("You must set either `.scope` or `.rate` for '%s' throttle" % self.__class__.__name__) raise ImproperlyConfigured(msg) try: return self.THROTTLE_RATES[self.scope] #正常情况下返回要给self.THROTTLE_RATES的[self.scope].这个scope是None,没有写,THROTTLE_RATES是THROTTLE_RATES = api_settings.DEFAULT_THROTTLE_RATES #也就是去配置文件DEFAULT_THROTTLE_RATES内获取的,这里我们可以通过,列表下标scope,也可以用字典key作为scope反正是能取到那个值就行。 except KeyError: msg = "No default throttle rate set for '%s' scope" % self.scope raise ImproperlyConfigured(msg)
需要配置的值,之前我们是看过的,再说一遍self.parse_rate(self.rate)内部:
def parse_rate(self, rate): """ Given the request rate string, return a two tuple of: <allowed number of requests>, <period of time in seconds> """ if rate is None: return (None, None) num, period = rate.split('/') #参数是以斜杠分割,前面是访问次数,后面是s/m或者H/D num_requests = int(num) duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]] return (num_requests, duration)
那么根据以上分析:配置文件就这样写
REST_FRAMEWORK ={ 'DEFAULT_AUTHENTICATION_CLASSES':['API.utils.auth.Authtication',], 'DEFAULT_THROTTLE_CLASSES':['API.utils.throttle.myThrottle',], #这里等会就不能用这个了,后面再改。 'DEFAULT_THROTTLE_RATES':{'Access':'10/m'} }
现在就差一个KEY了。赶快再去自定义一个类。写个key的获取方法就ok了
class myThrottle3(SimpleRateThrottle):
scope = 'Access' #配置文件中获取的key
def get_cache_key(self, request, view):
"""
父类中没有写的需要我们写的。这里可以用IP,或者用户名作为key来保存记录到django缓存。
:param request:
:param view:
:return:
SimpleRateThrottle类继承于BaseThrottle,他里面有个方法,get_ident。返回就是我们需要的IP
"""
key = self.get_ident(request)
print(key)
return key
配置文件中使用我们新定义的类。
REST_FRAMEWORK ={ 'DEFAULT_AUTHENTICATION_CLASSES':['API.utils.auth.Authtication',], 'DEFAULT_THROTTLE_CLASSES':['API.utils.throttle.myThrottle3',], 'DEFAULT_THROTTLE_RATES':{'Access':'3/m'} }
这样全局使用这个类,如果局部不使用,跟之前一样视图内定义throttle_classes赋值一个空列表,或者自定义的其他类。