自定义频率类和频率源码分析

自定义频率类

1 频率类
2 视图类
3 路由
4 频率源码分析

1 频率类

'''
# 写限制逻辑
	 # (1)取出访问者ip
	 # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,
	 	在字典里,继续往下走
	 # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,
	 	把这种数据pop掉,这样列表中只有60s以内的访问时间,
	 # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,
	 	返回True,顺利通过
	 # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
	 # return False
	 # 频率类写好,配置在视图类上,就会走它
'''

class MyThrottle(BaseThrottle):
    VISIT_RECORD = {}

    def __init__(self):
        self.history = []

    def allow_request(self, request, view):
        # 写限制逻辑
        # (1)取出访问者ip
        ip = request.META.get('REMOTE_ADDR')

        import time
        ctime = time.time()
        # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,
        # 表示第一次访问,在字典里,继续往下走
        if ip not in self.VISIT_RECORD:
            self.VISIT_RECORD[ip] = [ctime, ]
            return True
        # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,
        #  把这种数据pop掉,这样列表中只有60s以内的访问时间,
        self.history = self.VISIT_RECORD[ip]
        while self.history and ctime - self.history[-1] > 60:
            self.history.pop()
        # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
        if len(self.history) < 3:
            self.history.insert(0, ctime)
            return True
        # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
        # return False
        # 频率类写好,配置在视图类上,就会走它
        return False

    def wait(self):
        import time
        ctime = time.time()
        return 60 - (ctime - self.history[-1])

2 视图类类

from rest_framework.viewsets import GenericViewSet

from .throttling import MyThrottle


class BookView(GenericViewSet):
    throttle_classes = [MyThrottle]

    def list(self, request):
        print(self.request)
        return Response('测试自定义频率')

3 路由

from django.contrib import admin
from django.urls import path

from rest_framework.routers import SimpleRouter

router = SimpleRouter()
router.register('books', BookView, 'books')

urlpatterns = [
    path('admin/', admin.site.urls),
]

urlpatterns += router.urls

4 频率源码分析

# 1 频率源码
	-APIView----disaptch---》self.initial(request, *args, **kwargs)---416行:self.check_throttles(request)----352行 check_throttles
    
    def check_throttles(self, request):
        # self.get_throttles()就是咱们配置在视图类上频率类的对象列表[频率类对象,]
        for throttle in self.get_throttles():
            # 执行频率类对象的allow_request,传了2个,返回True或False
            if not throttle.allow_request(request, self):
                # 反会给前端失败,显示还剩多长时间能再访问
                throttle_durations.append(throttle.wait())

                
# 2 频率类要写
	1 写一个类,继承,BaseThrottle
    2 在类中重写:allow_request方法,传入 3个参数
    3 在allow_request写限制逻辑,如果还能访问--》返回True
    4 如果超了次数,就不能访问,返回False
    5 局部配置在视图类上
    6 全局配置在配置文件中
    
# 3 我们在drf中写的时候,不需要继承 BaseThrottle,继承了SimpleRateThrottle,重写get_cache_key
   -我们猜测:一定是 SimpleRateThrottle帮咱们写了咱们需要写的
    
    
    
# 4 自定义频率类,实现一分钟只能访问三次的控制:
	    # (1)取出访问者ip
        # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
        # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
        # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
        # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
        
        
        
#5  SimpleRateThrottle 源码分析
	- SimpleRateThrottle内部一定有:allow_request---def allow_request(self, request, view):
        # 咱们没写,以后咱们可以在频率类中直接写
        # rate='3/m'   以后不用写scope了,就会按一分钟访问3次现在
        if self.rate is None:
            return True
		# 取出:重写的get_cache_key返回的值,咱们返回了访问者ip
        self.key = self.get_cache_key(request, view)
        if self.key is None:
            return True
		# 根据当前访问者ip,取出 这个人的访问时间列表  [访问时间1,访问2,访问3,访问4]
        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()
        # 判断访问时间列表是否大于 3 
        if len(self.history) >= self.num_requests:
            return self.throttle_failure()
        return self.throttle_success()

你可能感兴趣的:(django,DRF,restframework,django,python)