Python django rest框架限制每个用户和每个视图

Python django rest框架限制每个用户和每个视图,python,django-rest-framework,throttling,Python,Django Rest Framework,Throttling,我有两个api视图(django rest框架): 及api 2: class ApiView2(APIView): ... throttle_classes = (UserRateThrottle, ) 和我的设置: REST_FRAMEWORK = { ..., 'DEFAULT_THROTTLE_RATES': { 'user': '5/minute' } } 当五次请求ApiView1时,一切正常,但之后当请求ApiView2时

我有两个api视图(django rest框架):

及api 2:

class ApiView2(APIView):
    ...
    throttle_classes = (UserRateThrottle, )
和我的设置:

REST_FRAMEWORK = {
    ...,
    'DEFAULT_THROTTLE_RATES': {
        'user': '5/minute'
    }
}
当五次请求ApiView1时,一切正常,但之后当请求ApiView2时,我会得到一个http 429状态代码,其中包含:

Request was throttled. Expected available in 45 seconds.
问题:我可以对每个用户和每个视图使用限制吗?如果是,怎么做?

是的,你可以

对于基于类的视图:

class YourView(APIView):
    throttle_classes = (UserRateThrottle, )

    def get(self, request, format=None):
        content = { ... Your response here ... }
        return Response(content)
对于基于函数的视图,可以使用decorator:
@throttle\u类([userratetrottle])


_参考资料:

,因为它是的特性

ScopedRateThrottle类可用于限制对API特定部分的访问。仅当正在访问的视图包含.throttle\u scope属性时,才会应用此限制。然后,通过将请求的“范围”与唯一的用户id或IP地址连接起来,形成唯一的节流键

允许的请求速率由使用请求“范围”中的键的默认\u THROTTLE\u RATES设置确定

由于没有在任何视图中设置节流范围,因此
ApiView1
ApiView2
都使用相同的节流范围
scope
。所以他们有相同的限制。如果一个视图被过度访问,另一个视图也将不可接受

在您的场景中,您应该在apiview中设置不同的throttle\u范围,并将该范围添加到
REST\u FRAMEWORK.DEFAULT\u throttle\u RATES

如果您有许多节流作用域,并且不想在
settings.py
中添加太多作用域,则应创建自己的
throttle
类,并覆盖
get\u cache\u key
功能

class MyThrottle(UserRateThrottle):
    def get_cache_key(self, request, view):
        return "throttle_{viewid}_{indent}".format(
            viewid=id(view),
            indent=self.get_indent(request)
        )

这个ThrottleClass可以为不同的视图自动设置不同的范围。

谢谢你的回复,我做了同样的事情,但是当对两个APIView使用
UserRateThrottle
时,throttling汇总两个视图的所有请求计数,换句话说,如果我想为每个api视图都设置默认的throttle速率,我希望每个视图都设置throttle(单独评分),那么除了将所有范围(100个视图,然后100个范围)添加到设置之外,还有其他解决方案吗?我更新了答案,您可以使用
MyThrottle
类。
class MyThrottle(UserRateThrottle):
    def get_cache_key(self, request, view):
        return "throttle_{viewid}_{indent}".format(
            viewid=id(view),
            indent=self.get_indent(request)
        )