我有一个视图集,我想只对该视图集的create
动作应用节流,我不希望它应用于update
,destroy
,retrieve
等…
class UserViewSet(viewsets.ModelViewSet):
# should only be applied to the create action
throttle_classes = [SomeThrottle]
...
正如在Introspecting ViewSet actions [DRF docs]中所描述的那样,您可以检查action
属性,通过覆盖get_throttles
方法来根据当前操作设置throttle_classes
:
class UserViewSet(viewsets.ModelViewSet):
def get_throttles(self):
if self.action == 'create':
throttle_classes = [SomeThrottle]
else:
throttle_classes = [] # No throttle for other actions
return [throttle() for throttle in throttle_classes]
如果使用ScopedRateThrottle
代替自定义节流
# settings
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.ScopedRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'submit': '1/minute',
}
class SomeViewSet(mixins.CreateModelMixin, GenericViewSet)
....
def get_throttles(self):
if self.action == 'create':
self.throttle_scope = 'submit'
return super().get_throttles()
为了方便,我构建了一个Mixin。您可以在ViewSet上使用它,并将throttle_action_classes
属性设置为throttle_classes的字典,其中键是操作,值是该操作的throttle_classes列表。
class ThrottlePerActionMixin(object):
"""
This mixing let you define throttles_classes per actions by passing a dict to throttle_action_classes attribute.
The throttle_classes on throttle_action_classes will be added to the default's ViewSet throttle_classes.
eg.:
class MyViewSet(ModelViewSet):
throttle_action_classes = {
'create': [CustomThrottleClass],
'retrieve': [AnonThrottleClass]
}
"""
def __init__(self, *args, **kwargs):
if not getattr(self, 'throttle_action_classes', None) or
isinstance(self.throttle_action_classes, (list, tuple)):
raise Exception("Must set throttle_action_classes as a dict. "
"eg.: throttle_action_classes = {'create': [CustomThrottle]}")
super().__init__(*args, **kwargs)
def get_throttles(self):
throttles = super().get_throttles()
for action, throttle_classes_for_action in self.throttle_action_classes.items():
if self.action == action:
if not isinstance(throttle_classes_for_action, (list, tuple)):
throttle_classes_for_action = [throttle_classes_for_action]
for throttle_class in throttle_classes_for_action:
throttles.append(throttle_class()) # The throttles_class needs to be instantiated.
return throttles