限流组件Throttling
- 可以对接口访问的频次进行限制,以减轻服务器压力,或者实现特定的业务。一般用于付费购买次数,投票等场景使用.
可选限流类
- 1.AnonRateThrottle :限制所有匿名未认证用户,使用IP区分用户。
- 使用
DEFAULT_THROTTLE_RATES['anon']
来设置频次
- 2.UserRateThrottle:限制认证用户,使用User id 来区分。
- 使用
DEFAULT_THROTTLE_RATES['user']
来设置频次
前两类的使用,在配置文件中配置,
x REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle' ),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
'DEFAULT_THROTTLE_RATES': {
'anon': '3/minute',
'user': '10/minute',
'access': '5/minute',
}
前两类的使用,在视图函数中配置
- 可以在具体视图中通过throttle_classess属性来配置,如
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView
class ExampleView(APIView):
throttle_classes = [UserRateThrottle,]
...
- 3.ScopedRateThrottle :限制用户对于每个视图的访问频次,使用ip或user id
- <1>.给对应的视图类的 throttle_scope类属性 定义一个名字
- <2>.在配置文件中配置好
-示例代码:
class ContactListView(APIView):
throttle_scope = 'contacts'
...
class ContactDetailView(APIView):
throttle_scope = 'contacts'
...
class UploadView(APIView):
throttle_scope = 'uploads'
...
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'contacts': '1000/day',
'uploads': '20/day'
}
}
实例代码:
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'anon': '3/minute',
'user': '10/minute',
'access': '5/minute',
}
}
from students.models import Student
from students.serializers import StudentModelSerializer
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import AllowAny,IsAuthenticated,IsAuthenticatedOrReadOnly,IsAdminUser
from .permission import ISMingGe
from rest_framework.throttling import UserRateThrottle,AnonRateThrottle,ScopedRateThrottle
class Students8APIView(ModelViewSet):
serializer_class = StudentModelSerializer
queryset = Student.objects.all()
permission_classes = [AllowAny]
throttle_classes = [ScopedRateThrottle]
throttle_scope = 'access'
实例代码--限制用户提交数据的时间(5分钟可以提交一次数据)
代码示例:
from rest_framework.viewsets import ModelViewSet
from django_filters.rest_framework import DjangoFilterBackend
from django_filters import FilterSet,filters
from rest_framework.throttling import SimpleRateThrottle
from rest_framework import exceptions,status
from app01.serializers.news import NewsSerializer
from app01 import models
from app01 import status_code
class ThrottledException(exceptions.APIException):
status_code = status.HTTP_429_TOO_MANY_REQUESTS
default_code = 'throttled'
class NewThrottle(SimpleRateThrottle):
THROTTLE_RATES = {"user":"1/5m"}
cache_format = 'throttle_%(scope)s_%(ident)s'
scope = "user"
def get_cache_key(self, request, view):
'''设置该用户缓存的唯一标识'''
ident = request.user.pk
return self.cache_format % {'scope': self.scope, 'ident': ident}
def parse_rate(self, rate):
'''
重写父类的该方法,可以自定义限速的条件,
因为原方法中,只能设置 1/m(1分钟一次) ,不能设置 1/5m(5分钟一次)
'''
if rate is None:
return (None, None)
num, period = rate.split('/')
num_requests = int(num)
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[-1]]
count = int(period[0:-1])
return (num_requests, count * duration)
def throttle_failure(self):
wait = self.wait()
detail = {
"code":status_code.THROTTLE_ERROR,
"error":"发布受限制,还需要等{}秒才能发布".format(wait)
}
raise ThrottledException(detail)
def throttle_success(self):
'''
因为父类代码中,只要访问过该url就会被限速,
在用户提交错误数据时,也被限速,所以将该方法默认都为通过,
只有在用户提交数据成功,且保存数据成功后,才会被限速
:return:
'''
return True
def done(self):
'''
自定义的方法,
防止用户提交数据错误时,也被限速,
所以只有当用户提交数据成功时,才会调用次方法,才会被限速
'''
self.history.insert(0, self.now)
self.cache.set(self.key, self.history, self.duration)
class NewsView(ModelViewSet):
filter_backends = [DjangoFilterBackend]
filterset_class = NewsFilter
serializer_class = NewsSerializer
queryset = models.News.objects.filter(deleted=False).order_by("-id")
throttle_classes = [NewThrottle(), ]
def get_queryset(self):
token = self.request.query_params.get("token")
user_obj = models.UserInfo.objects.filter(token=token).first()
queryset = self.queryset.filter(user=user_obj)
return queryset
def perform_create(self, serializer):
serializer.save(user=self.request.user)
for throttle in self.get_throttles():
throttle.done()
def get_throttles(self):
if self.request.method == "POST":
return self.throttle_classes
return []
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本