详解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 相关文章推荐
wxpython中利用线程防止假死的实现方法
Aug 11 Python
跟老齐学Python之眼花缭乱的运算符
Sep 14 Python
初学Python函数的笔记整理
Apr 07 Python
用Python遍历C盘dll文件的方法
May 06 Python
python更改已存在excel文件的方法
May 03 Python
3分钟学会一个Python小技巧
Nov 23 Python
django多对多表的创建,级联删除及手动创建第三张表
Jul 25 Python
Python线程障碍对象Barrier原理详解
Dec 02 Python
OpenCV+python实现实时目标检测功能
Jun 24 Python
Pycharm配置autopep8实现流程解析
Nov 28 Python
python opencv实现直线检测并测出倾斜角度(附源码+注释)
Dec 31 Python
python利用pandas分析学生期末成绩实例代码
Jul 09 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将字符串转换成16进制的方法
2015/03/17 PHP
thinkphp框架下实现登录、注册、找回密码功能
2016/04/06 PHP
PHP CURL采集百度搜寻结果图片不显示问题的解决方法
2017/02/03 PHP
js 刷新页面的代码小结 推荐
2010/04/02 Javascript
IE8下Jquery获取select选中的值post到后台报错问题
2014/07/02 Javascript
jQuery手动点击实现图片轮播特效
2020/04/20 Javascript
由浅入深讲解Javascript继承机制与simple-inheritance源码分析
2015/12/13 Javascript
基于jQuery实现放大镜特效
2020/10/19 Javascript
jquery实现跳到底部,回到顶部效果的简单实例(类似锚)
2016/07/10 Javascript
javascript如何创建对象
2016/08/29 Javascript
Gulp实现静态网页模块化的方法详解
2018/01/09 Javascript
网页爬虫之cookie自动获取及过期自动更新的实现方法
2018/03/06 Javascript
详解vuex的简单使用
2018/03/12 Javascript
微信小程序日期选择器实例代码
2018/07/18 Javascript
[48:53]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS VG第一场
2014/05/26 DOTA
[01:07:11]Secret vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
深入理解Javascript中的this关键字
2015/03/27 Python
python查询sqlite数据表的方法
2015/05/08 Python
Python爬虫框架Scrapy实战之批量抓取招聘信息
2015/08/07 Python
Python脚本简单实现打开默认浏览器登录人人和打开QQ的方法
2016/04/12 Python
Python re正则表达式元字符分组()用法分享
2020/02/10 Python
新手学python应该下哪个版本
2020/06/11 Python
手把手教你从PyCharm安装到激活(最新激活码),亲测有效可激活至2089年
2020/11/25 Python
ASP.NET Core中的配置详解
2021/02/05 Python
大学军训感言
2014/01/10 职场文书
写演讲稿要注意的六件事
2014/01/14 职场文书
个人自我鉴定总结
2014/03/25 职场文书
爱护公物标语
2014/06/24 职场文书
2014年大学学生会工作总结
2014/12/02 职场文书
学生保证书
2015/01/16 职场文书
离婚纠纷代理词
2015/05/23 职场文书
雷锋的观后感
2015/06/10 职场文书
创业计划书介绍
2019/04/24 职场文书
2019最新版试用期劳动合同模板!
2019/07/04 职场文书
javascript遍历对象的五种方式实例代码
2021/10/24 Javascript
一次SQL查询优化原理分析(900W+数据从17s到300ms)
2022/06/10 SQL Server