Django REST framework使用及源码分析之节流
节流,访问次数控制。
views.py
class OrderView(APIView): ''' 订单相关业务,返回订单字典。 添加验证功能,验证是否已登录。 ''' # authentication_classes = [Authtication,] # permission_classes = [MyPermission1, ] throttle_classes=[VisitThrottle,] '''该刚就是添加Authtication认证,可以添加多个,如果是一个空列表,则不认证,也就是可以跳过认证''' def get(self,request,*args,**kwargs): ret = {'code':1000,'msg':None} try: ret['data'] = ORDER_DICT except Exception as e: pass return JsonResponse(ret)
增加一个局部设置,throttle_classes
访问控制类:
import time VISIT_RECORD={} class VisitThrottle(object): ''' 节流控制,返回True为通过访问,False为限制访问。 ''' def allow_request(self,request,view): remote_addr = request.META.get('REMOTE_ADDR') #获取访问的IP print(remote_addr) ctime = time.time() if remote_addr not in VISIT_RECORD: #判断ip是存在,不存在则把ip和时间记录,然后通过访问。 VISIT_RECORD[remote_addr] = [ctime,] return True history = VISIT_RECORD.get(remote_addr) #如果ip存在,则找到这个对应的时间 print(VISIT_RECORD) self.history = history while history and history[-1] < ctime - 10: #循环,找到这个ip对应的时间列表,如果最早的历史时间小于当前时间减去10秒,那么将其删除 history.pop() if len(history) <3: '''如果列表长度小于3,则将当前时间添加到列表索引0的位置,也就是最前面''' history.insert(0,ctime) return True def wait(self): '''还有多久可以访问 通过用限制时间减去(当前时间减去历史最早时间),将时间返回,系统将自动发给前端。''' ctime = time.time() return 10 - (ctime - self.history[-1])
全局设置:
REST_FRAMEWORK = { # 全局使用的认证类 "DEFAULT_AUTHENTICATION_CLASSES":['app.utils.auth.Authtication', ], "UNAUTHENTICATED_USER":None, # 匿名,request.user = None "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None "DEFAULT_PERMISSION_CLASSES":['app.utils.permission.MyPermission1'], "DEFAULT_THROTTLE_CLASSES":["app.utils.throttle.VisitThrottle"], }
源码流程梳理:
基本和验证、权限差不多。
除了上面这种自定义的节流控制,REST framework有个自带的节流控制,比较方便。
节流类:
from rest_framework.throttling import BaseThrottle,SimpleRateThrottle class VisitThrottle(SimpleRateThrottle): scope = "Luffy" def get_cache_key(self, request, view): return self.get_ident(request) class UserThrottle(SimpleRateThrottle): scope = "LuffyUser" def get_cache_key(self, request, view): return request.user.username
只需实现get_cache_key,配置文件添加配置即可。
scope只是一个字符串,当做字典的key
get_ident 是针对匿名用户的,根据Ip控制。
request.user.username 通过用户名控制。
配置:
REST_FRAMEWORK = { # 全局使用的认证类 "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication','api.utils.auth.Authtication', ], # "DEFAULT_AUTHENTICATION_CLASSES":['api.utils.auth.FirstAuthtication', ], # "UNAUTHENTICATED_USER":lambda :"匿名用户" "UNAUTHENTICATED_USER":None, # 匿名,request.user = None "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None "DEFAULT_PERMISSION_CLASSES":['api.utils.permission.SVIPPermission'], "DEFAULT_THROTTLE_CLASSES":["api.utils.throttle.UserThrottle"], "DEFAULT_THROTTLE_RATES":{ "Luffy":'3/m', "LuffyUser":'10/m', } }
上面配置,需要些字典的key:时间/单位。
中天一片无情月,是我平生不悔心