一、访问频率控制的使用
- 1.创建自己的频率控制类,继承
BaseThrottle
class MyThrottling(throttling.BaseThrottle):
def allow_request(self, request, view):
# 返回 True,则表示可以继续访问
# 返回 False,则表示访问频率过高,进行限制
# 这里通过IP进行限制,60秒内只能访问3次
remote_addr = request.META.get('REMOTE_ADDR')
history: list = remote_dict.get(remote_addr, None)
ctime = time.time()
if not history: # 初次访问
remote_dict[remote_addr] = [ctime, ]
return True
while history and history[-1] - ctime >= 60:
history.pop()
if len(history) < 3:
history.insert(0, ctime)
return True
-
2.将
MyThrottling进行配置- 1)在 具体
View视图类中,添加类属性,仅在该视图类中有效
class OrderView(APIView): throttle_classes = [MyThrottling, ] def post(self, request, *args, **kwargs): pass- 2)在
settings.py中进行全局配置,所有资源都有效
# settings.py REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES': ['api.utils.throttl.MyThrottling', ] } - 1)在 具体
二、使用rest_framework 提供的SimpleRateThrottle
- 1.继承
SimpleRateThrottle,并重写get_cache_key(self, request, view)与scope属性
from rest_framework import throttling
class IPThrottling(throttling.SimpleRateThrottle):
scope = 'IP_rate'
def get_cache_key(self, request, view):
return 'cache_' + self.get_ident()
- 2.在settings.py文件中进行配置,设置访问频率(可以设置多个,根据
scope进行匹配)
# settings.py
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'IP_rate': '3/m'
}
}
注意点:
- 控制用户的访问频率需要先确认
用户身份,SimpleRateThrottle中通过get_cache_key返回用户标示,在上述我们返回'cache_' + self.get_ident().
而get_ident()返回的是用户IP,所以SimpleRateThrottle是基于ip进行限制的。
- 控制用户的访问频率需要先确认
- 我们可以设置多个频率控制,对不同的资源,采用不同的频率[通过
scope进行指定]。设置频率的格式为3/m就是每一分钟允许3次。m就是代表60秒.
除了m,还可以采用以下:
- 我们可以设置多个频率控制,对不同的资源,采用不同的频率[通过
{'s': 1, 'm': 60, 'h': 3600, 'd': 86400}
三、对SimpleRateThrottle进行定制化
SimpleRateThrottle是基于ip进行验证,我们可以继承SimpleRateThrottle重写get_cache_key方法。
rest_framework提供的UserRateThrottle就是基于django的用户系统以及ip进行频率控制的。
class UserRateThrottle(SimpleRateThrottle):
"""
Limits the rate of API calls that may be made by a given user.
The user id will be used as a unique cache key if the user is
authenticated. For anonymous requests, the IP address of the request will
be used.
"""
scope = 'user'
def get_cache_key(self, request, view):
if request.user.is_authenticated:
# 返回用户标示
ident = request.user.pk
else:
# 返回`ip`标示
ident = self.get_ident(request)
return self.cache_format % {
'scope': self.scope,
'ident': ident
}









网友评论