详解Django-restframework 之频率源码分析


Posted in Python onFebruary 27, 2019

一 前言

经过权限判断之后就是进行频率的判断了,而频率的判断和权限又不一样,认证、权限和频率的执行流程都差不多,使用配置里面的相关类来进行判断。而不和认证和权限一样,频率的配置没有,查看 APIView 的类属性如下:

详解Django-restframework 之频率源码分析

详解Django-restframework 之频率源码分析

二 频率组件执行流程

虽然 restframework 原生灭有配置频率,但是提供了几个进行频率判断的类,如下:

详解Django-restframework 之频率源码分析

其中 SimpleRateThrottle 类是根据访问者 ip 来进行频率限制的一个类,来看看这个类的执行流程。

1. init方法

详解Django-restframework 之频率源码分析

2. get_rate

详解Django-restframework 之频率源码分析

3. 执行 allow_request方法

详解Django-restframework 之频率源码分析

4. get_cache_key

详解Django-restframework 之频率源码分析

5. 时间差判断

详解Django-restframework 之频率源码分析

6. throttle_success

详解Django-restframework 之频率源码分析

认证失败的话执行 throttle_failure ,其实就是返回 False

7. wait

详解Django-restframework 之频率源码分析

三 自定义频率组件

1. 自定义频率类

频率类需要继承自带的频率类

# from rest_framework.throttling import BaseThrottle

class BookThrottle(BaseThrottle):

  VISIT_RECORD = {}

  def __init__(self):
    self.history = None

  def allow_request(self, request, view):
    print(request.META)
    REMOTE_ADDR = request.META.get('REMOTE_ADDR')

    import time
    ctime = time.time()
    if REMOTE_ADDR not in self.VISIT_RECORD:
      self.VISIT_RECORD[REMOTE_ADDR] = [ctime,]
      return True
    self.history = self.VISIT_RECORD.get(REMOTE_ADDR)

    while self.history and ctime - self.history[-1] > 60:
      self.history.pop()

    if len(self.history) < 3:
      self.history.insert(0, ctime)
      return True
    else:
      return False

  def wait(self):
    import time
    ctime = time.time()

    return 60 - (ctime - self.history[-1])
# 频率类代码注释
     # 访问频率的逻辑
#     #   {'ip地址':[16:13:39,16:13:19,],'ip地址2':[时间1,时间2],}
#     # (1)取出访问者ip
#     # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
#     # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
#     # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
#     # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
#     #(1)取出访问者ip
#     # print(request.META)
#     # REMOTE_ADDR 就是访问者的ip:127.0.0.1
#     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,]
#       # {'127.0.0.1':[时间1,时间1,]}
#       return True
#     # self.history=[时间1,时间1,]
#     self.history=self.VISIT_RECORD.get(ip)
#     # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
#     while self.history and ctime-self.history[-1]>60:
#       self.history.pop()
#     # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
#     # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
#     if len(self.history)<3:
#       self.history.insert(0,ctime)
#       return True
#     else:
#       return False

2. 使用

使用很简单,在需要进行频率控制的视图类中定义一个属性 throttle_classes ,如下:

class Book(APIView):
  authentication_classes = [authticate_classes.BookAuth]
  permission_classes = [permiss_classes.LoginPermission]
  throttle_classes = [thrott_classes.BookThrottle]
  # authentication_classes = []

  def dispatch(self, request, *args, **kwargs):
    return super().dispatch(request, *args, **kwargs)

  def get(self, request, id):
    print(request.user, '444')
    response = {'status': 100, 'msg': None}
    book_obj = models.Book.objects.filter(pk=id).first()
    if book_obj:
      book_ser = myser.BookSer(book_obj, many=False)
      response['book'] = book_ser.data
    else:
      response['msg'] = '图书没有对象'
      response['status'] = 101
    return Response(response)

四 配置自定义频率类

 1. 局部配置

其实上面的就是局部配置,

class Book(APIView):
  authentication_classes = [authticate_classes.BookAuth]
  permission_classes = [permiss_classes.LoginPermission]
  throttle_classes = [thrott_classes.BookThrottle]

2. 全局使用

全局配置如下:

REST_FRAMEWORK={
  'DEFAULT_THROTTLE_CLASSES': ['app01.thrott_classes.BookThrottle']
}

3. 局部禁用

局部禁用需要在视图类中定义一个空的 throttle_classes 属性

throttle_classes = []

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 命令行参数sys.argv
Sep 06 Python
python使用Berkeley DB数据库实例
Sep 26 Python
详解Python中DOM方法的动态性
Apr 11 Python
巧用python和libnmapd,提取Nmap扫描结果
Aug 23 Python
Python处理PDF及生成多层PDF实例代码
Apr 24 Python
分享几道你可能遇到的python面试题
Jul 24 Python
python并发2之使用asyncio处理并发
Dec 21 Python
python实现爬取图书封面
Jul 05 Python
Python生成rsa密钥对操作示例
Apr 26 Python
Python 文件数据读写的具体实现
Jan 24 Python
通过代码实例了解Python3编程技巧
Oct 13 Python
Python+Appium自动化测试的实战
Jun 30 Python
Python的UTC时间转换讲解
Feb 26 #Python
Python逐行读取文件中内容的简单方法
Feb 26 #Python
Python计算时间间隔(精确到微妙)的代码实例
Feb 26 #Python
python3编写ThinkPHP命令执行Getshell的方法
Feb 26 #Python
初探利用Python进行图文识别(OCR)
Feb 26 #Python
Python编写合并字典并实现敏感目录的小脚本
Feb 26 #Python
Python实现监控Nginx配置文件的不同并发送邮件报警功能示例
Feb 26 #Python
You might like
无数据库的详细域名查询程序PHP版(5)
2006/10/09 PHP
php更改目录及子目录下所有的文件后缀扩展名的代码
2010/10/12 PHP
php数组删除元素示例
2014/03/21 PHP
PHP下的Oracle客户端扩展(OCI8)安装教程
2014/09/10 PHP
PHP实现仿百度文库,豆丁在线文档效果(word,excel,ppt转flash)
2016/03/10 PHP
php批量删除操作代码分享
2017/02/26 PHP
Prototype RegExp对象 学习
2009/07/19 Javascript
Prototype Array对象 学习
2009/07/19 Javascript
解析JavaScript中的标签语句
2013/06/19 Javascript
jQuery中addClass()方法用法实例
2015/01/05 Javascript
jQuery的事件预绑定
2016/12/05 Javascript
Angular工具方法学习
2016/12/26 Javascript
angular实现form验证实例代码
2017/01/17 Javascript
AngularJS前端页面操作之用户修改密码功能示例
2017/03/27 Javascript
基于JS实现仿京东搜索栏随滑动透明度渐变效果
2017/07/10 Javascript
Angular4编程之表单响应功能示例
2017/12/13 Javascript
vue两个组件间值的传递或修改方式
2018/07/04 Javascript
vue中子组件传递数据给父组件的讲解
2019/01/27 Javascript
python提取图像的名字*.jpg到txt文本的方法
2018/05/10 Python
使用PyInstaller将python转成可执行文件exe笔记
2018/05/26 Python
python 统计列表中不同元素的数量方法
2018/06/29 Python
python批量创建指定名称的文件夹
2019/03/21 Python
python单例模式的多种实现方法
2019/07/26 Python
Python3.6实现根据电影名称(支持电视剧名称),获取下载链接的方法
2019/08/26 Python
为什么黑客都用python(123个黑客必备的Python工具)
2020/01/31 Python
django实现后台显示媒体文件
2020/04/07 Python
全网首秀之Pycharm十大实用技巧(推荐)
2020/04/27 Python
Python 添加文件注释和函数注释操作
2020/08/09 Python
Spy++的使用方法及下载教程
2021/01/29 Python
马智宇结婚主持词
2014/04/01 职场文书
个人总结怎么写
2015/02/26 职场文书
新教师教学工作总结
2015/08/14 职场文书
Python实现查询剪贴板自动匹配信息的思路详解
2021/07/09 Python
SQL实现LeetCode(178.分数排行)
2021/08/04 MySQL
Spring boot admin 服务监控利器详解
2022/08/05 Java/Android
Python  序列化反序列化和异常处理的问题小结
2022/12/24 Python