zoukankan      html  css  js  c++  java
  • django rest_framework 框架的使用02

    rest_framework 访问频率的限制(节流)

    对于用户访问频率的显示,rest_framework 也有自己的类进行约束

    • 先来一个自己的基于它的类的节流类的限制
    class VisitControl(BaseThrottle):
        """
        访问评论限制
        """
        def __init__(self):
    
            self.history = None
        def allow_request(self, request, view):
    
            ctime = time.time()
            remote_addr = self.get_ident(request)
    
            if remote_addr not in VISIT_DICT:
                VISIT_DICT[remote_addr] = [ctime, ]
                return True
    
            history_list = VISIT_DICT.get(remote_addr)
            self.history = history_list
            
            """
            history_list[-1] < ctime - 10
    
            这个--> 如果当前的时间 减去 60秒 之后 与列表里面的 最后一个 就是最早访问的 时间 比较
            
            如果 比他大 证明 这个 时间 无效了 ,把他 去除 ,然后在比较前一个  直到 
            
            当前时间 减去60秒之后 比 最后一个小, 证明 这个时间在60秒内,第一个条件就符合了
        
            
            然后 剩下的 列表里面的值就都符合了(因为 列表里面最前面的元素 时间约靠近当下时间)
            
            然后拿着这个列表里面的值 去判断 (因为这些值都是 60 秒内访问的) 如果小于3 证明 你还有一次机会
    
            让他访问 ,但是 需要 把他加到 列表里面去,
            以便下次判断列表个数的时候使用(每次符合要求的时间都需要加到列表里面,共后续使用)
             
            """
    
            while history_list and history_list[-1] < ctime - 10:
                history_list.pop()
    
            if len(history_list) < 3:
                history_list.insert(0, ctime)
                return True
    
        def wait(self):
    
            ctime = time.time()
    
            return 60 - (ctime - self.history[-1])
    
    
    

    其实rest_framework已经为我们提供了基于用户的节流类,以及基于IP的节流类,我们只需要继承这个两个类 分别实现各自的方法即可:

    
    class UserThrottle(SimpleRateThrottle):
    
        scope = "User"  # 登录用户访问频率的限制
    
        def get_cache_key(self, request, view):
            return request.user.username
    
    
    
    class IpThrottle(SimpleRateThrottle):
    
        scope = "AsyUser"  # 匿名用户访问频率的限制
    
        def get_cache_key(self, request, view):
            return self.get_ident(request)
    
    """
    注意的是全局的settings配置如下
    """
    
    
    "DEFAULT_AUTHENTICATION_CLASSES": ["api.utils.permission.MyAuthtication",],  # 认证全局配置
        "DEFAULT_PERMISSION_CLASSES": [],  # 权限的  全局配置
        # 节流的频率控制
        "DEFAULT_THROTTLE_RATES": {
            "Luffy": "10/m",
            "User": "20/m"
    
        },
    # 节流的类,默认是没有的!
    "DEFAULT_THROTTLE_CLASSES": ["api.utils.permission.UserThrottle",]
    
    
    rest_framework版本控制

    首先是自己写在url的get请求的版本控制比如
    url="xxxxxx/?version=v1"
    对应的类方法如下:

    class MyVersion(BaseVersioning):
        """
        自己 的类的方法
        """
        def determine_version(self, request, *args, **kwargs):
            version = request.query_params.get("version")
            return version
    
    
    
    看一下其他部分的源码:
    ##  版本的控制的
    ## version 是版本号,这个scheme 是你的解析版本的类
    ## 解析版本的类只允许有一个
    version, scheme = self.determine_version(request, *args, **kwargs)
    # 版本赋值给 request.version 类赋值给request.versioning_scheme
    request.version, request.versioning_scheme = version, scheme
    
    

    一般使用这个内之类即可

    from rest_framework.versioning import URLPathVersioning
    
    class URLPathVersioning(BaseVersioning):
        """
        To the client this is the same style as `NamespaceVersioning`.
        The difference is in the backend - this implementation uses
        Django's URL keyword arguments to determine the version.
    
        An example URL conf for two views that accept two different versions.
    
        urlpatterns = [
            url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),
            url(r'^(?P<version>[v1|v2]+)/users/(?P<pk>[0-9]+)/$', users_detail, name='users-detail')
        ]
    
        GET /1.0/something/ HTTP/1.1
        Host: example.com
        Accept: application/json
        """
        invalid_version_message = _('Invalid version in URL path.')
    
        def determine_version(self, request, *args, **kwargs):
            version = kwargs.get(self.version_param, self.default_version)
            if not self.is_allowed_version(version):
                raise exceptions.NotFound(self.invalid_version_message)
            return version
    
        def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
            if request.version is not None:
                kwargs = {} if (kwargs is None) else kwargs
                kwargs[self.version_param] = request.version
    
            return super(URLPathVersioning, self).reverse(
                viewname, args, kwargs, request, format, **extra
            )
    
    
    
  • 相关阅读:
    梦断代码阅读笔记03
    梦断代码阅读笔记01
    构建之法阅读笔记03
    《构建之法——现代软件工程》读书笔记(一)
    构建之法阅读笔记02
    TypeError: only integer scalar arrays can be converted to a scalar index
    LeetCode Easy: 33. Search in Rotated Sorted Array
    LeetCode Medium: 31. Next Permutation
    LeetCode Medium: 29. Divide Two Integers
    python中merge、concat用法
  • 原文地址:https://www.cnblogs.com/zjcode/p/9410901.html
Copyright © 2011-2022 走看看