DRF-Throttle组件源码分析及改编源码
1. 限流组件源码分析
注意:以下源码为方便理解已进行简化,只保留了与限流组件相关的代码。注释前的数字代表执行顺序。


SimpleRateThrottle类的源码解析:

2. 实践:编写一个限流类
from rest_framework.throttling import SimpleRateThrottle
from django.core.cache import cache as default_cache
class IpThrottle(SimpleRateThrottle):
scope = "ip" # 节流类的名称
# THROTTLE_RATES = {"x1": "5/m"} 类中未定义THROTTLE_RATES则去settings中获取
cache = default_cache # 节流类指定写入的缓存
def get_cache_key(self, request, view):
ident = self.get_ident(request) # 获取请求用户IP(去request中找请求头)
return self.cache_format % {'scope': self.scope, 'ident': ident}
class UserThrottle(SimpleRateThrottle):
scope = "user" # 节流类的名称
# THROTTLE_RATES = {"x1": "5/m"} 类中未定义THROTTLE_RATES则去settings中获取
cache = default_cache # 节流类指定写入的缓存
def get_cache_key(self, request, view):
ident = request.user.pk # 用户ID
return self.cache_format % {'scope': self.scope, 'ident': ident}
3. 源码改编
- 重写限流的时长规则:原本只支持 1分钟x次,重写后支持 x分钟x次:
def parse_rate(self, rate):
'''重写获取时长的parse_rate方法,原本只能写1/m或2/m,现在支持:1/5m, 3/10m的格式'''
if rate is None:
return (None, None)
num, period = rate.split('/') # "1/5m"
num_requests = int(num)
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[-1]]
count = int(period[0:-1])
return (num_requests, duration * count)
- 请求操作失败时,不计入限流次数
# 思路:在视图的操作成功后再进行计入操作(throttle_success)
# 限流类中: 重写throttle_success操作,并把计次的操作提取出来,自定义一个函数,在视图操作成功后才调用该函数进行计次
class MyThrottle(SimpleRateThrottle):
def throttle_success(self):
# self.history.insert(0, self.now)
# self.cache.set(self.key, self.history, self.duration)
return True
def done(self):
""" 视图函数执行成功后,再调用throttle_success里的方法"""
self.history.insert(0, self.now)
self.cache.set(self.key, self.history, self.duration)
# 视图类中:
class MyView(APIView):
def post(request):
"""中间代码省略"""
# 成功操作后才记录一次限流
for throttle in self.get_throttles():
throttle.done()
- 自定义限流类的报错信息
# 在限流类中:
# 自定义抛出报错的异常类
class ThrottledException(exceptions.APIException):
status_code = status.HTTP_429_TOO_MANY_REQUESTS
default_code = 'throttled'
#重写throttle_failure方法,自定义报错信息并直接抛出异常;
def throttle_failure(self):
wait = self.wait()
detail = {
"code": return_code.TOO_MANY_REQUESTS,
"data": "访问频率限制",
'detail': "需等待{}秒后才能访问".format(int(wait))
}
raise ThrottledException(detail)
DRF-Throttle组件源码分析及改编源码的更多相关文章
- drf的基本使用、APIView源码分析和CBV源码拓展
cbv源码拓展 扩展,如果我在Book视图类中重写dispatch方法 -可以实现,在get,post方法执行之前或者之后执行代码,完成类似装饰器的效果 def dispatch(self, requ ...
- NIO 源码分析(05) Channel 源码分析
目录 一.Channel 类图 二.begin 和 close 是什么 2.1 AbstractInterruptibleChannel 中的 begin 和 close 2.2 Selector 中 ...
- NIO 源码分析(02-2) BIO 源码分析 Socket
目录 一.BIO 最简使用姿势 二.connect 方法 2.1 Socket.connect 方法 2.2 AbstractPlainSocketImpl.connect 方法 2.3 DualSt ...
- NIO 源码分析(02-1) BIO 源码分析
目录 一.BIO 最简使用姿势 二.ServerSocket 源码分析 2.1 相关类图 2.2 主要属性 2.3 构造函数 2.4 bind 方法 2.5 accept 方法 2.6 总结 NIO ...
- [源码分析] 从实例和源码入手看 Flink 之广播 Broadcast
[源码分析] 从实例和源码入手看 Flink 之广播 Broadcast 0x00 摘要 本文将通过源码分析和实例讲解,带领大家熟悉Flink的广播变量机制. 0x01 业务需求 1. 场景需求 对黑 ...
- Spring Ioc源码分析系列--Ioc源码入口分析
Spring Ioc源码分析系列--Ioc源码入口分析 本系列文章代码基于Spring Framework 5.2.x 前言 上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了I ...
- k8s client-go源码分析 informer源码分析(3)-Reflector源码分析
k8s client-go源码分析 informer源码分析(3)-Reflector源码分析 1.Reflector概述 Reflector从kube-apiserver中list&watc ...
- 5.2 spring5源码--spring AOP源码分析三---切面源码分析
一. AOP切面源码分析 源码分析分为三部分 1. 解析切面 2. 创建动态代理 3. 调用 源码的入口 源码分析的入口, 从注解开始: 组件的入口是一个注解, 比如启用AOP的注解@EnableAs ...
- jQuery1.11源码分析(1)-----Sizzle源码概览[原创]
最近在啃jQuery1.11源码,上来就遇到Sizzle这个jQuery的大核心,虽然已经清楚了Sizzle的用途,先绕过去也没事,但明知山有虎偏向虎山行才是我们要做的. 本文面向的阅读对象:正在学习 ...
- 【MyBatis源码分析】select源码分析及小结
示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...
随机推荐
- 最佳实践:解读GaussDB(DWS) 统计信息自动收集方案
摘要:现在商用优化器大多都是基于统计信息进行查询代价评估,因此统计信息是否实时且准确对查询影响很大,特别是分布式数据库场景.本文详细介绍GaussDB(DWS)如何实现了一种轻量.实时.准确的统计信息 ...
- Python的OpenCV转换图像大小
在Python中,使用OpenCV库来转换图像大小是一个常见的操作,它可以帮助你调整图像到特定的尺寸,以适应不同的应用场景,比如图像预处理.模型输入等.下面是一个详细的代码示例,展示了如何使用Open ...
- canfestival源码下载教程
先进入官网的这个页面 https://canfestival.org/code.html.en 点击箭头所指的地方 选择日期最新的点击下载
- Ubuntu 安裝 RIME 輸入法
RIME (Rime Input Method Engine,中州韻,中州韵)是一款很火的輸入法,虽然我目前还不知道它为什么火,不过先用用再说. 首先要吐槽一下 RIME 的说明文档,我感觉有点乱,第 ...
- PowerShell 使用
Practice 常用命令 vim $PROFILE # 编辑配置文件 Get-ChildItem *> $null # 抛弃所有输出 whoami Remove-Item -Recurse - ...
- Could not resolve placeholder 'xxx.xxx.xxx' in value "http://${xxx.xxx.xxx}"
代码一切正常,忽然报这个错误, 原因为,当前配置在配置文件最后,且前面均为注释,把当前配置位置提前即可
- Android : Found byte-order-mark in the middle of a file
1. 首先,打包App,然后打包报错, views里提示,要加上 android { lintOptions { checkReleaseBuilds false //不检查发布版中的错误 abort ...
- 开发Android应用程序,在Android10的系统上提示网络出错?
今天维护以前开发的一个Android客户端程序,发版后,有用户说自己手机安装,无法登录,首屏打开后(有网络通过接口加载服务器数据并显示的行为),提示网络出错. 但是我在我自己手上的PDA设备(Andr ...
- 消息队列的对比测试与RocketMQ使用扩展
消息队列的对比测试与RocketMQ使用扩展 本文的主要内容包括以下几个方面: 原有的消息技术选型 RocketMQ与kafka 测试对比 如何构建自己的消息队列服务 RocketMQ扩展改造 ...
- 总结篇3:redis 典型缓存架构设计问题及性能优化
聊聊对于缓存预热.缓存穿透.缓存雪崩.缓存击穿.缓存更新.缓存降级的定义理解 缓存穿透 定义 当查询Redis中没有的数据时,该查询会下沉到数据库层,同时数据库层也没有该数据,当这种情况大量出现或被恶 ...