rest-framework之频率控制

本文目录

一 频率简介

为了控制用户对某个url请求的频率,比如,一分钟以内,只能访问三次

二 自定义频率类,自定义频率规则

自定义的逻辑

  1. #(1)取出访问者ip
  2. # (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
  3. # (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
  4. # (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
  5. # (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败

代码实现:

  1. class MyThrottles():
  2. VISIT_RECORD = {}
  3. def __init__(self):
  4. self.history=None
  5. def allow_request(self,request, view):
  6. #(1)取出访问者ip
  7. # print(request.META)
  8. ip=request.META.get('REMOTE_ADDR')
  9. import time
  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. import time
  28. ctime=time.time()
  29. return 60-(ctime-self.history[-1])

三 内置频率类及局部使用

写一个类,继承自SimpleRateThrottle,(根据ip限制)问:要根据用户现在怎么写

  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)

在setting里配置:(一分钟访问三次)

  1. REST_FRAMEWORK = {
  2. 'DEFAULT_THROTTLE_RATES':{
  3. 'luffy':'3/m'
  4. }
  5. }

在视图类里使用

  1. throttle_classes = [MyThrottles,]

错误信息的中文提示:

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

内置频率限制类:

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

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

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

UserRateThrottle:登录用户频率限制,这个得配合auth模块来用

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

四 内置频率类及全局使用

  1. REST_FRAMEWORK = {
  2. 'DEFAULT_THROTTLE_CLASSES':['app01.utils.VisitThrottle',],
  3. 'DEFAULT_THROTTLE_RATES':{
  4. 'luffy':'3/m'
  5. }
  6. }

五 源码分析

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

SimpleRateThrottle源码分析

rest-framework之频率控制的更多相关文章

  1. Django Rest Framework源码剖析(三)-----频率控制

    一.简介 承接上篇文章Django Rest Framework源码剖析(二)-----权限,当服务的接口被频繁调用,导致资源紧张怎么办呢?当然或许有很多解决办法,比如:负载均衡.提高服务器配置.通过 ...

  2. windows类书的学习心得

    原文网址:http://www.blogjava.net/sound/archive/2008/08/21/40499.html 现在的计算机图书发展的可真快,很久没去书店,昨日去了一下,真是感叹万千 ...

  3. Django REST framework 内置访问频率控制

    对匿名用户采用 IP 控制访问频率,对登录用户采用 用户名 控制访问频率. from rest_framework.throttling import SimpleRateThrottle class ...

  4. Django Rest Framework(二)

    •基于Django 先创建一个django项目,在项目中创建一些表,用来测试rest framework的各种组件 models.py class UserInfo(models.Model): &q ...

  5. Django Rest framework 框架之认证使用和源码执行流程

    用这个框架需要先安装: pip3 install djangorestframework 如果写了一个CBV的东西,继承了View. # 继承Django里面View class APIView(Vi ...

  6. Django之REST framework源码分析

    前言: Django REST framework,是1个基于Django搭建 REST风格API的框架: 1.什么是API呢? API就是访问即可获取数据的url地址,下面是一个最简单的 Djang ...

  7. django rest framework restful 规范

    内容回顾: . django请求生命周期 -> 执行遵循wsgi协议的模块(socket服务端) -> 中间件(路由匹配) -> 视图函数(业务处理:ORM.模板渲染) -> ...

  8. django的rest framework框架——认证、权限、节流控制

    一.登录认证示例 模拟用户登录,获取token,当用户访问订单或用户中心时,判断用户携带正确的token,则允许查看订单和用户信息,否则抛出异常: from django.conf.urls impo ...

  9. Django REST Framework之频率限制

    开放平台的API接口调用需要限制其频率,以节约服务器资源和避免恶意的频繁调用 使用 自定义频率限制组件:utils/thottle.py class MyThrottle(BaseThrottle): ...

  10. Django REST Framework概述

    什么是REST REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”.这里说的表征性,就是指资源,通 ...

随机推荐

  1. x=x+1, x += 1, x++ 效率分析

    x = x + 1 效率最低 具体如下: 1. 读取右x的地址 2. x + 1 3. 读取左x的地址 4. 将右值传给左边的x(编译器不认为左x和右x是同一个地址) x += 1 其次 1. 读取右 ...

  2. ID基本操作(新建文档,页面编码)5.8

    “文件”“新建”“文档”选择页数,页面大小.页面方向,“边距和分栏”设置上下左右的边距,栏数,如三栏 还可以改变分栏距离·改变排版方向,如图,垂直 单击“页面”可以查看我们的页面情况 超过两页会可以看 ...

  3. python 自然语言处理(三)____条件频率分布

    条件频率分布就是频率分布的集合,每个频率分布有一个不同的“条件”,这个条件通常是文本的类别.当语料文本分为几类(文体,主题,作者等)时,可以计算每个类别独立的频率分布,这样,就可以通过条件频率分布研究 ...

  4. 对大学生学习Linux系统的七项实用建议

    你现在的工作是你所渴望的理想工作吗?或者说这只是你整个职业生涯中的一段插曲?虽然我们每个人都不一定能够说出自己所想的是什么,但是我们心里其实跟明镜似的.相信许多人对于自己喜好的工作投入精力不会有问题, ...

  5. HTML(五)选择器--伪类选择器

    HTML代码 <body> <a href="www.baidu.com">www.baidu.com</a> </body> CS ...

  6. 第二节 java流程控制(判断结构+选择结构)

    Java的判断结构: 1.if(条件表达式){ 执行语句 }: 2.if(条件表达式){ 执行语句 }else{ 执行语句 } 3. if(条件表达式){ 执行语句 }else if(条件表达式){ ...

  7. mysql ON DUPLICATE KEY UPDATE ; 以及 同replace to 的区别.

    需求: 1)如果admin表中没有数据, 插入一条 2)如果admin表中有数据, 不插入. 一般做法: if($result = mysql_query("select * from ad ...

  8. chromium ②

    这篇研究两个问题:chromium对线程的封装和进程通信.主要参考chromium的官方技术文档:Treading和Inter-process Communication (IPC). chrome速 ...

  9. jetty调优

    jetty服务器使用遇到一下内存溢出的问题: java.lang.OutOfMemoryError: unable to create new native thread   无法创建新的进程 方法: ...

  10. python Django rest-framework 创建序列化工程步骤

    11创建项目 2创建应用 3stting添加应用(apps)-添加制定数据库-修改显示汉字(zh-hans)-上海时区(Asia/Shanghai) 4主路由添加子路由 5应用里创建子路由 6创建数据 ...