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


    自定义频率类

    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])
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    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('测试自定义频率')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
  • 相关阅读:
    HTML本地离线缓存?
    【Linux笔记】Linux环境变量与地址空间
    H3CNE-6-ICMP数据包分析
    C#:实现鸡尾酒定向冒泡排序算法(附完整源码)
    小程序一键链接WIFI
    接口幂等性最佳实践--redis+注解
    ES6 入门教程 3 变量的解构赋值 3.3 字符串的解构赋值 & 3.4 数值和布尔值的解构赋值 ~ 3.7 用途
    Python:如何在一个月内学会爬取大规模数据
    redhat下使用CentOS yum源,并安装docker
    推荐一个免费的相亲工具
  • 原文地址:https://blog.csdn.net/weixin_44145338/article/details/132904121