详解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的Tornado框架实现一个Web端图书展示页面
Jul 11 Python
用Python实现随机森林算法的示例
Aug 24 Python
Django中ORM表的创建和增删改查方法示例
Nov 15 Python
Python清空文件并替换内容的实例
Oct 22 Python
快速解决vue.js 模板和jinja 模板冲突的问题
Jul 26 Python
python 直接赋值和copy的区别详解
Aug 07 Python
Python 读取用户指令和格式化打印实现解析
Sep 02 Python
在vscode中配置python环境过程解析
Sep 28 Python
tensorflow获取预训练模型某层参数并赋值到当前网络指定层方式
Jan 24 Python
python 字典item与iteritems的区别详解
Apr 25 Python
python批量修改文件名的示例
Sep 27 Python
Selenium关闭INFO:CONSOLE提示的解决
Dec 07 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
如何在WIN2K下安装PHP4.04
2006/10/09 PHP
解析PHP将对象转换成数组的方法(兼容多维数组类型)
2013/06/21 PHP
PHP用mysql_insert_id()函数获得刚插入数据或当前发布文章的ID
2016/11/25 PHP
PHP第三方登录―QQ登录实现方法
2017/02/06 PHP
php经典趣味算法实例代码
2020/01/21 PHP
一个不错的用JavaScript实现的UBB编码函数
2007/03/09 Javascript
javascript 实现父窗口引用弹出窗口的值的脚本
2007/08/07 Javascript
javascript 定义初始化数组函数
2009/09/07 Javascript
JQuery中each()的使用方法说明
2010/08/19 Javascript
js获得鼠标的坐标值的方法
2013/03/13 Javascript
JS实现旋转木马式图片轮播效果
2017/01/18 Javascript
基于Vue实现微信小程序的图文编辑器
2018/07/25 Javascript
详解Node.js读写中文内容文件操作
2018/10/10 Javascript
webpack项目使用eslint建立代码规范实现
2019/05/16 Javascript
vscode调试node.js的实现方法
2020/03/22 Javascript
python3 面向对象__类的内置属性与方法的实例代码
2018/11/09 Python
树莓派动作捕捉抓拍存储图像脚本
2019/06/22 Python
pd.DataFrame统计各列数值多少的实例
2019/12/05 Python
简单了解python shutil模块原理及使用方法
2020/04/28 Python
keras之权重初始化方式
2020/05/21 Python
对Python 字典元素进行删除的方法
2020/07/31 Python
用HTML5制作一个简单的弹力球游戏
2015/05/12 HTML / CSS
以设计师精品品质提供快速时尚:Mostata
2019/05/10 全球购物
银行实习生的自我评价
2013/12/09 职场文书
土木建筑学生自我评价
2014/01/14 职场文书
经理管理专业毕业自荐书范文
2014/02/12 职场文书
根叔历年演讲稿
2014/05/20 职场文书
节能环保演讲稿
2014/08/28 职场文书
2014旅游局领导班子四风问题对照检查材料思想汇报
2014/09/19 职场文书
幼儿园学前班幼儿评语
2014/12/29 职场文书
医药公司开票员岗位职责
2015/04/15 职场文书
2015年办公室个人工作总结
2015/04/20 职场文书
奔腾年代观后感
2015/06/09 职场文书
职工食堂管理制度
2015/08/06 职场文书
Nginx配置之实现多台服务器负载均衡
2021/08/02 Servers
pt-archiver 主键自增
2022/04/26 MySQL