频率组件简介

主要是为了限制用户访问的次数,比如某一个接口(发送验证码)同一个手机号一分钟内只能访问一次。

自定义频率类

规则:

  • 用户对某个url请求的频率,一分钟以内只能访问三次

思路:

  1. 回去访问者IP
  2. 判断当前IP是否在访问字典里面,不在就添加进去,并且返回True,表示第一次访问
  3. 循环判断当前IP的列表,有值,并且当前时间减去列表的最后一个时间大于60秒,把这种数据pop掉,这样列表中只存在60秒之内的访问时间
  4. 然后判断列表的长度,如果小于3,表示一分钟之内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
  5. 当大于等于3,说明一分钟内访问超过三次,返回False验证失败

第一种:手撸频率类

  1. import time
  2. class MyThrottles():
  3. VISIT_RECORD = {}
  4. def __init__(self):
  5. self.history=None
  6. def allow_request(self,request, view):
  7. #(1)取出访问者ip
  8. # print(request.META)
  9. ip=request.META.get('REMOTE_ADDR')
  10. ctime=time.time()
  11. # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问
  12. if ip not in self.VISIT_RECORD:
  13. self.VISIT_RECORD[ip]=[ctime,]
  14. return True
  15. self.history=self.VISIT_RECORD.get(ip)
  16. # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
  17. while self.history and ctime-self.history[-1]>60:
  18. self.history.pop()
  19. # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
  20. # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
  21. if len(self.history)<3:
  22. self.history.insert(0,ctime)
  23. return True
  24. else:
  25. return False
  26. def wait(self):
  27. ctime=time.time()
  28. return 60-(ctime-self.history[-1])

第二种:继承SimpleRateThrottle

  1. from rest_framework.throttling import SimpleRateThrottle
  2. class VisitThrottle(SimpleRateThrottle):
  3. scope = 'luffy'
  4. def get_cache_key(self, request, view):
  5. return self.get_ident(request)
  6. """
  7. 在settings.py中配置访问频率
  8. REST_FRAMEWORK = {
  9. 'DEFAULT_THROTTLE_RATES':{
  10. 'luffy':'3/m'
  11. }
  12. }
  13. """

内置频率类及局部使用

  • BaseThrottle:是所有类的基类

    方法:def get_ident(self, request)获取标识,其实就是获取ip,自定义的需要继承它;

  • AnonRateThrottle:未登录用户ip限制,需要配合auth模块用;

  • SimpleRateThrottle:重写此方法,可以实现频率限制,不需要咱们手写上面自定义的逻辑;

  • UserRateThrottle:登录用户频率限制,这个也需要配合auth模块来用;

  • ScopedRateThrottle:应用在局部视图上的(忽略)

**在视图类里使用: **

  1. throttle_classes = [MyThrottles,]

错误信息的中文提示:

  1. class Course(APIView):
  2. authentication_classes = [TokenAuth, ]
  3. permission_classes = [UserPermission, ]
  4. throttle_classes = [MyThrottles,]
  5. def get(self, request):
  6. return HttpResponse('get')
  7. def post(self, request):
  8. return HttpResponse('post')
  9. def throttled(self, request, wait):
  10. from rest_framework.exceptions import Throttled
  11. class MyThrottled(Throttled):
  12. default_detail = '傻逼啊'
  13. extra_detail_singular = '还有 {wait} second.'
  14. extra_detail_plural = '出了 {wait} seconds.'
  15. raise MyThrottled(wait)

全局使用

  1. # 在settings.py中进行配置
  2. REST_FRAMEWORK = {
  3. 'DEFAULT_THROTTLE_CLASSES':['app01.utils.VisitThrottle',],
  4. 'DEFAULT_THROTTLE_RATES':{
  5. 'luffy':'3/m'
  6. }
  7. }

源码分析

  1. def check_throttles(self, request):
  2. for throttle in self.get_throttles():
  3. if not throttle.allow_request(request, self):
  4. self.throttled(request, throttle.wait())
  5. def throttled(self, request, wait):
  6. #抛异常,可以自定义异常,实现错误信息的中文显示
  7. raise exceptions.Throttled(wait)

SimpleRateThrottle源码分析

  1. class SimpleRateThrottle(BaseThrottle):
  2. # 我们自己写的放在了全局变量,他的在django的缓存中
  3. cache = default_cache
  4. # 获取当前时间,跟咱写的一样
  5. timer = time.time
  6. # 做了一个字符串格式化,
  7. cache_format = 'throttle_%(scope)s_%(ident)s'
  8. scope = None
  9. # 从配置文件中取DEFAULT_THROTTLE_RATES,所以咱配置文件中应该配置,否则报错
  10. THROTTLE_RATES = api_settings.DEFAULT_THROTTLE_RATES
  11. def __init__(self):
  12. if not getattr(self, 'rate', None):
  13. # 从配置文件中找出scope配置的名字对应的值,比如咱写的‘3/m’,他取出来
  14. self.rate = self.get_rate()
  15. # 解析'3/m',解析成 3 m
  16. self.num_requests, self.duration = self.parse_rate(self.rate)
  17. # 这个方法需要重写
  18. def get_cache_key(self, request, view):
  19. """
  20. Should return a unique cache-key which can be used for throttling.
  21. Must be overridden.
  22. May return `None` if the request should not be throttled.
  23. """
  24. raise NotImplementedError('.get_cache_key() must be overridden')
  25. def get_rate(self):
  26. if not getattr(self, 'scope', None):
  27. msg = ("You must set either `.scope` or `.rate` for '%s' throttle" %
  28. self.__class__.__name__)
  29. raise ImproperlyConfigured(msg)
  30. try:
  31. # 获取在setting里配置的字典中的之,self.scope是 咱写的luffy
  32. return self.THROTTLE_RATES[self.scope]
  33. except KeyError:
  34. msg = "No default throttle rate set for '%s' scope" % self.scope
  35. raise ImproperlyConfigured(msg)
  36. # 解析 3/m这种传参
  37. def parse_rate(self, rate):
  38. """
  39. Given the request rate string, return a two tuple of:
  40. <allowed number of requests>, <period of time in seconds>
  41. """
  42. if rate is None:
  43. return (None, None)
  44. num, period = rate.split('/')
  45. num_requests = int(num)
  46. # 只取了第一位,也就是 3/mimmmmmmm也是代表一分钟
  47. duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
  48. return (num_requests, duration)
  49. # 逻辑跟咱自定义的相同
  50. def allow_request(self, request, view):
  51. """
  52. Implement the check to see if the request should be throttled.
  53. On success calls `throttle_success`.
  54. On failure calls `throttle_failure`.
  55. """
  56. if self.rate is None:
  57. return True
  58. self.key = self.get_cache_key(request, view)
  59. if self.key is None:
  60. return True
  61. self.history = self.cache.get(self.key, [])
  62. self.now = self.timer()
  63. # Drop any requests from the history which have now passed the
  64. # throttle duration
  65. while self.history and self.history[-1] <= self.now - self.duration:
  66. self.history.pop()
  67. if len(self.history) >= self.num_requests:
  68. return self.throttle_failure()
  69. return self.throttle_success()
  70. # 成功返回true,并且插入到缓存中
  71. def throttle_success(self):
  72. """
  73. Inserts the current request's timestamp along with the key
  74. into the cache.
  75. """
  76. self.history.insert(0, self.now)
  77. self.cache.set(self.key, self.history, self.duration)
  78. return True
  79. # 失败返回false
  80. def throttle_failure(self):
  81. """
  82. Called when a request to the API has failed due to throttling.
  83. """
  84. return False
  85. def wait(self):
  86. """
  87. Returns the recommended next request time in seconds.
  88. """
  89. if self.history:
  90. remaining_duration = self.duration - (self.now - self.history[-1])
  91. else:
  92. remaining_duration = self.duration
  93. available_requests = self.num_requests - len(self.history) + 1
  94. if available_requests <= 0:
  95. return None
  96. return remaining_duration / float(available_requests)

drf--频率组件的更多相关文章

  1. drf 频率组件 META字典详情

    drf频率组件 什么是频率 控制用户对某个url的请求频率,比如一分钟之内,只能访问三次 自定义频率规则 1.取出访问者ip 2.判断当前ip在不在访问字典中: 不在,则添加进去,返回True; 3. ...

  2. drf频率组件

    1.简介 控制访问频率的组件 2.使用 手写一个自定义频率组件 import time #频率限制 #自定义频率组件,return True则可以访问,return False则不能访问 class ...

  3. DRF框架(七) ——三大认证组件之频率组件、jwt认证

    drf频率组件源码 1.APIView的dispatch方法的  self.initial(request,*args,**kwargs)  点进去 2.self.check_throttles(re ...

  4. 【DRF频率】

    目录 使用自带的频率限制类 使用自定义的频率限制类 开发平台的API接口调用需要限制其频率,以节约服务器资源和避免恶意的频繁调用. DRF就为我们提供了一些频率限制的方法. DRF中的版本.认证.权限 ...

  5. DRF(5) - 频率组件、url注册器、响应器、分页器

    一.频率组件 1.使用DRF简单频率控制实现对用户进行访问频率控制 1)导入模块,定义频率类并继承SimpleRateThrottle # 导入模块 from rest_framework.throt ...

  6. DRF之权限认证频率组件

    概要 retrieve方法源码剖析 认证组件的使用方式及源码剖析 权限组件的使用方式及源码剖析 频率组件的使用方式及源码剖析 知识点复习回顾 Python逻辑运算 知识点复习回顾一:Python逻辑运 ...

  7. Django框架深入了解_03(DRF之认证组件、权限组件、频率组件、token)

    一.认证组件 使用方法: ①写一个认证类,新建文件:my_examine.py # 导入需要继承的基类BaseAuthentication from rest_framework.authentica ...

  8. drf框架 - 三大认证组件 | 认证组件 | 权限组件 | 频率组件

    RBAC 基于用户权限访问控制的认证 - Role-Based Access Control Django框架采用的是RBAC认证规则,RBAC认证规则通常会分为 三表规则.五表规则,Django采用 ...

  9. drf token刷新配置、认证组件(使用)、权限组件(使用)、频率组件(使用)、异常组件(使用)

    目录 一.特殊路由映射的请求 二.token刷新机制配置(了解) 三.认证组件项目使用:多方式登录 1.urls.py 路由 2.views.py 视图 3.serializers.py 序列化 4. ...

  10. drf三大组件之频率认证组件

    复习 """ 1.认证组件:校验认证字符串,得到request.user 没有认证字符串,直接放回None,游客 有认证字符串,但认证失败抛异常,非法用户 有认证字符串, ...

随机推荐

  1. 视频合并时使用python批量修改文件名

    不知道大家有没有遇到这样的情况,比如视频合并时文件名没有按照正常顺序排列,像这样 可见,文件名排序是乱的.这个样子合并出来的视频一定也是乱的.所以得想办法把文件名修改一下,让软件读取出正确的顺序.闲话 ...

  2. destoon中get_maincat函数的用法

    求解get_maincat函数的用法,如get_maincat(0, $CATEGORY, 1),其中第一.二.三个参数分别表示什么,有谁知道,请介绍下,谢谢! 答:get_maincat() 三个参 ...

  3. shell脚本如何判断文件大小

    转自:https://blog.csdn.net/lovegengxin/article/details/80762329 1 .ls -lls -l $filename | awk '{print ...

  4. svg形状相关的学习(二)

    _ 阅读目录 一:线段 二:笔画特性 1. stroke-width 2. stroke-opacity 3. stroke-dasharray 属性 三:常见的形状 1. 矩形 2. 圆角矩形 3. ...

  5. bootstrap基础自我总结

    *今天自学了一些封装的css,看起来官网很强大,但是因为源码备注都是英文的情况下,还是感觉想深入有点力不从心,发现度娘没有中文手册,无奈,不过还好代码无国界,基本都是能看懂的,备注也影响不大(安慰自己 ...

  6. restql 学习一 安装试用

    restql 提供了manager 可以方便配置restql 的资源,同时也提供了一个docker-compose 运行环境 以下是一个安装使用 环境准备 docker-compose 文件   ve ...

  7. ESA2GJK1DH1K微信小程序篇: 小程序实现MQTT封包源码使用说明

    说明 我为了后期能够快速的让小程序实现MQTT,我做了一个MQTT的封装. 功能的封装有助于后期快速的开发,还方便咱维护. 我后期的所有代码皆使用此封装库, 这一节,我就详细的介绍我封装的MQTT.j ...

  8. selenium--浏览器滚动条操作

    前戏 在进行web自动化的时候,selenium只能找当前屏幕上的标签,如果标签在当前页面没显示下,需要拖动滚动条才能查看到这个元素,这时候就要操作浏览器的滚动条,让当前页面显示这个元素才可以操作,在 ...

  9. 洛谷 P2023 [AHOI2009]维护序列 题解

    P2023 [AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列中 ...

  10. Perl 使用perl命令批量替换文件内容

    对linux系统下面多个文本文件内容做处理,是SA经常需要完成的工作.如何高效的完成这个工作,perl应该是一个不错的语言工具.你甚至不需要编写perl脚本,用命令就可以完成上面的工作. perl 命 ...