如何在Django REST Framework中实现按用户+按视图限流?
实现按用户且按视图的限流方案
当然可以实现!你现在遇到的问题是因为两个视图都用了默认的UserRateThrottle,它的限流范围(scope)是共享的'user',所以用户访问任意一个视图的次数都会累计到同一个计数器里,导致互相影响。要实现按用户+视图分别限流,有两种常用方案:
方法一:自定义UserRateThrottle子类
我们可以给每个视图创建专属的限流类,通过不同的scope来区分计数器:
- 首先定义两个自定义限流类,继承
UserRateThrottle并指定不同的scope:
from rest_framework.throttling import UserRateThrottle class View1UserThrottle(UserRateThrottle): # 给ApiView1专属的scope scope = 'view1_user' class View2UserThrottle(UserRateThrottle): # 给ApiView2专属的scope scope = 'view2_user'
- 修改两个视图的
throttle_classes,使用对应的自定义限流类:
class ApiView1(APIView): ... throttle_classes = (View1UserThrottle, ) class ApiView2(APIView): ... throttle_classes = (View2UserThrottle, )
- 在settings的
REST_FRAMEWORK配置里,给这两个scope分别设置限流速率:
REST_FRAMEWORK = { ..., 'DEFAULT_THROTTLE_RATES': { 'view1_user': '5/minute', 'view2_user': '5/minute' # 你也可以给不同视图设置不同的速率,比如'10/minute' } }
方法二:使用ScopedRateThrottle(更简洁)
DRF提供了ScopedRateThrottle类,允许直接在视图中指定throttle_scope属性,无需创建多个限流子类:
- 修改视图配置,使用
ScopedRateThrottle并指定各自的throttle_scope:
from rest_framework.throttling import ScopedRateThrottle class ApiView1(APIView): ... throttle_classes = (ScopedRateThrottle, ) throttle_scope = 'view1' class ApiView2(APIView): ... throttle_classes = (ScopedRateThrottle, ) throttle_scope = 'view2'
- 在settings中给对应的
scope配置限流速率:
REST_FRAMEWORK = { ..., 'DEFAULT_THROTTLE_RATES': { 'view1': '5/minute', 'view2': '5/minute' } }
原理说明
两种方案的核心都是通过不同的scope来区分独立的限流计数器。DRF会根据scope的值为每个用户+scope的组合维护单独的访问计数,这样用户访问ApiView1的次数就不会影响ApiView2的限流阈值,反之亦然。
内容的提问来源于stack exchange,提问作者Hadi Farhadi
相关产品推荐
相关产品推荐

