首先自定义一个访问频率的类,然后在试图中引用就可以了,如下:
1, 先定义访问频率的类,如下代码:没有继承restframework的任何类
# 下面是访问频率的代码,没有继承
# 这个代码根据访问的IP地址 来进行访问限制。。。。同理可作根据访问的用户名来进行访问限制。
#这里定义一个字典,用来记录访问频率, 这个字典的key就是ip地址,value就是访问的时间记录值是一个value,这个可以在这里用一个字典,也可以翻到缓存,也可以翻到数据库
VISIT_RECORD = {}
import time
from rest_framework.throttling import BaseThrottle
class VisitThrottle(object):
def __init__(self):
self.history = None
# 60秒内只能访问3次
def allow_request(self, request, view):
#return True 表示可以继续访问
#return False 表示访问频率太高,被限制了
#1, 获取用户的ip地址
remote_addr = request.META.get ('REMOTE_ADDR')
#判断ip在不在VISIT_RECORD里面,然后添加时间
ctime = time.time()
#下面的if语句是第一次访问的设置
if remote_addr not in VISIT_RECORD:
VISIT_RECORD[remote_addr] = [ctime,]
return True
history = VISIT_RECORD.get(remote_addr) #定义history历史记录,这里获取指定ip地址的访问列表
self.history = history #把这个赋值给整个类的变量,然后就可以给下面的wait()函数使用了
#下面定义一个循环,用来吧当前时间和history里面的时间进行比较,因为考虑用到列表的POP操作,所以这里我们把时间从前面插入,最近的时间在左边,最远的时间在右边
while history and history[-1] < ctime-60: #因为是一分钟中之内,所以是减60
history.pop() #如果最右边的时间小于当前时间减去60,那么执行pop操作,吧最右边的时间清空,这里可以循环比较,直到列表被清空。
#下面开始对访问的history的个数进行限制,如果小于3我们返回True ,表示可以继续访问
if len(history) < 3:
history.insert(0, ctime)#吧当前时间插入到第0个位置
return True
def wait(self):
# return 返回值,返回几,在页面会提示还剩多少秒可以继续访问,比如我们写 return 10 表示还剩10s可以继续访问
# 可以自定义动态的时间,然后返回,然后就会动态提示还剩多少秒返回
ctime = time.time()
left_time = 60-(ctime-self.history[-1])
return left_time
2, 在试图中是用:
class AuthView(APIView):
'''
用于用户登陆
这里拿到前台发过来的用户名和密码,然后去数据库校验,同时我们还生成了token,然后还给用户返回了token,用于用户后面发送请求,必须要
带上这个token的请求.
'''
# authentication_classes = [] #这里因为在全局中设置了验证类,所以在这里要把这个列表为空,好让这个视图可以不经过全局的验证,直接执行.
#访问频率的类列表设置
throttle_classes = [VisitThrottle,]
def get(self, request, *args, **kwargs):
return HttpResponse('hello workd')
def post(self, request, *args, **kwargs):
ret = {'code':1000, 'msg':None}
try:
user = request._request.POST.get('username')
password = request._request.POST.get('password')
obj = models.UserInfo.objects.filter(username=user, password=password).first()
if not obj:
ret['code'] = 1001
ret['msg'] = '用户名或者密码错误'
#未登陆用户创建token,采用上面定义的md5()函数来生成token
token = md5(user)
#保存金数据库,有就更新,没有就创建,因为是只能用最新的token,所以需要更新操作.
models.UserToken.objects.update_or_create(user=obj, defaults={'token':token})
#需要给用户返回token
ret['token'] = token
except Exception as e:
ret['code']=1002
ret['msg']='请求异常'
return JsonResponse(ret)
3, 也可以在全局中配置
REST_FRAMEWORK = {
# 'DEFAULT_AUTHENTICATION_CLASSES':['api.utils.auth.FirstAuthenticate',], #注意这个格式, 这里的DEFAULT_AUTHENTICATION_CLASSES是restframework 配置规定的, 后面的列表就是认证的类. 里面写的是认证类的路径
#下面两句是匿名用户的设置:
'UNAUTHENTICATED_USER':None, #匿名, 则request.user = None
'UNAUTHENTICATED_TOKEN':None, #匿名, 则request.token = None
# 'DEFAULT_PERMISSION_CLASSES':['api.utils.permission.MyPermission'],
'DEFAULT_THROTTLE_CLASSES': ['api.utils.throttle.MyThrottle']
}
定义继承自SimpleRateThrottle()类
1, 这个类中的设置
2, views.py 文件中的代码,继承的代码,如下:
# 下面是继承自SimpleRateThrottle类的实现,他这个类,已经帮我们实现好了基于IP的访问频率控制,只需要继承之后设置一些参数就可以了
from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
class VisitThrottle1(SimpleRateThrottle):
# scope = 'lxbai' #这个是自定义的,这个scope 用来设置访问频率的key的,这个设置了之后,就需要在settings.py中定义了,如果这里不写scope,只写下面的rate也是不错的,就是专门用来控制这个类的。
rate = '10/m' #这个参考源码,设置60秒10次。
#重写需要重写的函数
#把cache_key设置成id,就是把这个ip地址设置成key,然后history设置成value
def get_cache_key(self, request, view):
return self.get_ident(request)
解释1: 如果在这里设置scope了之后,就不用在这里设置rate了,就需要在settings.py中定义,如下:
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES':{
'lxbai': '10/m' #这个scope lxbai是我们在那个继承类中定义好的。
}
}
解释2:如果在这个不设置scope, 就用那个rate设置成rate='10/m’就可以了,也是一分钟访问10次。
总结: 这个部分有很多的设置,做的时候,参考原视频和源码。