详解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之大话题小函数(2)
Oct 10 Python
深度定制Python的Flask框架开发环境的一些技巧总结
Jul 12 Python
Python  pip安装lxml出错的问题解决办法
Feb 10 Python
Python数据结构之哈夫曼树定义与使用方法示例
Apr 22 Python
python3爬虫获取html内容及各属性值的方法
Dec 17 Python
基于numpy中的expand_dims函数用法
Dec 18 Python
python中如何使用insert函数
Jan 09 Python
Django设置Postgresql的操作
May 14 Python
python使用列表的最佳方案
Aug 12 Python
通俗易懂了解Python装饰器原理
Sep 17 Python
Python帮你解决手机qq微信内存占用太多问题
Feb 15 Python
详解Python+OpenCV绘制灰度直方图
Mar 22 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的access操作类
2008/04/09 PHP
解决phpmyadmin中缺少mysqli扩展问题的方法
2013/05/06 PHP
PHP的switch判断语句的“高级”用法详解
2014/10/01 PHP
php中解析带中文字符的url函数分享
2015/01/20 PHP
laravel框架路由分组,中间件,命名空间,子域名,路由前缀实例分析
2020/02/18 PHP
javascript Firefox与IE 替换节点的方法
2010/02/24 Javascript
javascript 闭包疑问
2010/12/30 Javascript
前端弹出对话框 js实现ajax交互
2016/09/09 Javascript
Javascript中常见的逻辑题和解决方法
2016/09/17 Javascript
ionic由于使用了header和subheader导致被遮挡的问题的两种解决方法
2016/09/22 Javascript
JavaScript 继承详解(六)
2016/10/11 Javascript
JavaScript 实现 Tab 点击切换实例代码
2017/03/25 Javascript
JS+HTML5 FileReader对象用法示例
2017/04/07 Javascript
AngularJS入门教程一:路由用法初探
2017/05/27 Javascript
用JavaScript做简易的购物车的代码示例
2017/10/20 Javascript
浅谈React中的元素、组件、实例和节点
2018/02/27 Javascript
webpack+vue-cli项目中引入外部非模块格式js的方法
2018/09/28 Javascript
vue2.0实现的tab标签切换效果(内容可自定义)示例
2019/02/11 Javascript
vue实现计算器功能
2020/02/22 Javascript
wxpython学习笔记(推荐查看)
2014/06/09 Python
跟老齐学Python之字典,你还记得吗?
2014/09/20 Python
Python实现的飞速中文网小说下载脚本
2015/04/23 Python
以一个投票程序的实例来讲解Python的Django框架使用
2016/02/18 Python
scrapy爬虫实例分享
2017/12/28 Python
python中将zip压缩包转为gz.tar的方法
2018/10/18 Python
利用Python制作动态排名图的实现代码
2020/04/09 Python
前端实现打印图像功能
2019/08/27 HTML / CSS
苹果台湾官网:Apple台湾
2019/01/05 全球购物
传播学毕业生求职信
2013/10/11 职场文书
材料成型及控制工程专业求职信
2014/06/19 职场文书
淘宝活动总结范文
2014/06/26 职场文书
大学生职业生涯规划大赛作品(精品)
2014/09/17 职场文书
2015年实习单位评语
2015/03/25 职场文书
2016大学迎新欢迎词
2015/09/29 职场文书
2019销售早会主持词
2019/06/27 职场文书
Java实现聊天机器人完善版
2021/07/04 Java/Android