django restframework框架四 截流
@(python之路)[django restframework框架四 截流]
django restframework框架四 截流
截流简介
用户的访问频率控制。我们把一个人访问的事件按戳添加列表中,或者是根据ip计数。例如:一分钟访问三次,过一分钟pop一次。
截流组件
这里我们把截流组件拿出来。以后用得时候可以直接导入取用。
我们写的也是参考源码。
from rest_framework.throttling import SimpleRateThrottle
class UserRateThrottle(SimpleRateThrottle):
scope = 'user'
def get_cache_key(self, request, view):
if request.user:
# 如果已经登录,pk
ident = request.user
else:
# 如果没有登录,IP
ident = self.get_ident(request)
# 'throttle_%(scope)s_%(ident)s'
# throttle_user_fengfeng
return self.cache_format % {
'scope': self.scope,
'ident': ident
}
def allow_request(self, request, view):
if request.auth.user.user_type == 1:
# self.num_requests = 3
# self.duration = 60
pass
else:
self.num_requests = 6
return super(UserRateThrottle,self).allow_request(request, view)
配置文件添加
添加如下这行:
# 此缓存将内容保存至文件
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
}
}
# 注:其他配置同开发调试版本
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES':{
'user':'3/m'
},
}
在调用缓存得时候,是调用得源码中
def allow_request(self, request, view):
if self.rate is None:
return True
self.key = self.get_cache_key(request, view)
if self.key is None:
return True
# 这里我们得history开始时空列表,随着用户得访问,我们将用户得时间戳添加近列表;
# 等过一定时间,pop调一个。
self.history = self.cache.get(self.key, [])
self.now = self.timer()
while self.history and self.history[-1] <= self.now - self.duration:
self.history.pop()
if len(self.history) >= self.num_requests:
return self.throttle_failure()
return self.throttle_success()
注意:这不是绝对得限制,我们可以针对注册用户做限制,匿名用户只能做,ip限制。限制也不是绝对得。
缓存配置文件
源码分析
我们 还是从dispatch
进入主流程,看他的initial
.
1
def initial(self, request, *args, **kwargs):
self.format_kwarg = self.get_format_suffix(**kwargs)
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
self.perform_authentication(request)
self.check_permissions(request)
# 截流频率
self.check_throttles(request)
这里就是截流具体要做的东西self.check_throttles(request)
,具体是怎么做的,我们接着看。
2
def check_throttles(self, request):
for throttle in self.get_throttles():
# 是否允许访问(allow_request)。如果不允许访问,就会抛出异常。
if not throttle.allow_request(request, self):
# 我们注意的是throttle.wait() 他是提示多久以后才可以访问
self.throttled(request, throttle.wait())
这里的self.get_throttles()
还是个列表生成式,在里面self.throttle_classes
这里边有它的默认配置。
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
在我们使用的时候需要导入
from rest_framework.throttling import BaseThrottle
源码分析:
3
class BaseThrottle(object):
def allow_request(self, request, view):
pass
def get_ident(self, request):
xff = request.META.get('HTTP_X_FORWARDED_FOR')
remote_addr = request.META.get('REMOTE_ADDR')
……
def wait(self):
pass
HTTP_X_FORWARDED_FOR
这里拿的是请求相关信息。
REMOTE_ADDR
拿的是ip。
4
# 匿名
class AnonRateThrottle(SimpleRateThrottle)
# 用户
class UserRateThrottle(SimpleRateThrottle)
# 范围
class ScopedRateThrottle(SimpleRateThrottle)
例子:
from rest_framework.throttling import SimpleRateThrottle
class UserView(APIView):
authentication_classes = [MyAuthtication,]
throttle_classes = [BaseThrottle,]
def get(self,request,*args,**kwargs):
self.dispatch
return HttpResponse("get")
def post(self,request,*args,**kwargs):
return HttpResponse("post")
def put(self,request,*args,**kwargs):
return HttpResponse("put")
def delete(self,request,*args,**kwargs):
return HttpResponse("delete")
当我们这么做的时候(throttle_classes = [BaseThrottle,]
),他会先做一步实例化。具体请看2
他是这样做的实例化。他会执行__init__.py
具体看一下:
class SimpleRateThrottle(BaseThrottle):
cache = default_cache
timer = time.time
cache_format = 'throttle_%(scope)s_%(ident)s'
scope = None
# DEFAULT_THROTTLE_RATES 定义访问频率的。
THROTTLE_RATES = api_settings.DEFAULT_THROTTLE_RATES
def __init__(self):
if not getattr(self, 'rate', None):
# 这里我们要具体分析get_rate具体做了什么。
self.rate = self.get_rate()
self.num_requests, self.duration = self.parse_rate(self.rate)
def get_rate(self):
if not getattr(self, 'scope', None):
msg = ("You must set either `.scope` or `.rate` for '%s' throttle" %
self.__class__.__name__)
raise ImproperlyConfigured(msg)
try:
# 找到我们的scope,scope=None
return self.THROTTLE_RATES[self.scope]
except KeyError:
msg = "No default throttle rate set for '%s' scope" % self.scope
raise ImproperlyConfigured(msg)
根据他在配置文件中添加得user:1/3
我们可以分析它的源码
class SimpleRateThrottle(BaseThrottle):
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('/')
num_requests = int(num)
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
return (num_requests, duration)
他是在这里做的处理;具体流程我们还需要在SimpleRateThrottle
类中具体看一下,这里不叫简单不在做详细得解释。
若有不懂得同学,可以留言。