From 886f8b47510c830483b5adae1855593cdc3df2dc Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 14 Sep 2012 08:54:58 +0100 Subject: [PATCH] Tweak throttles and improve docs --- djangorestframework/tests/throttling.py | 2 ++ djangorestframework/throttling.py | 11 +++++------ docs/api-guide/throttling.md | 23 +++++++++++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/djangorestframework/tests/throttling.py b/djangorestframework/tests/throttling.py index 9ee4ffa40..3033614f4 100644 --- a/djangorestframework/tests/throttling.py +++ b/djangorestframework/tests/throttling.py @@ -14,10 +14,12 @@ from djangorestframework.response import Response class User3SecRateThrottle(UserRateThrottle): rate = '3/sec' + scope = 'seconds' class User3MinRateThrottle(UserRateThrottle): rate = '3/min' + scope = 'minutes' class MockView(APIView): diff --git a/djangorestframework/throttling.py b/djangorestframework/throttling.py index f8b098d7b..6249bd421 100644 --- a/djangorestframework/throttling.py +++ b/djangorestframework/throttling.py @@ -44,7 +44,7 @@ class SimpleRateThottle(BaseThrottle): timer = time.time settings = api_settings - cache_format = '%(class)s_%(scope)s_%(ident)s' + cache_format = 'throtte_%(scope)s_%(ident)s' scope = None def __init__(self, view): @@ -144,7 +144,6 @@ class AnonRateThrottle(SimpleRateThottle): ident = request.META.get('REMOTE_ADDR', None) return self.cache_format % { - 'class': self.__class__.__name__, 'scope': self.scope, 'ident': ident } @@ -167,7 +166,6 @@ class UserRateThrottle(SimpleRateThottle): ident = request.META.get('REMOTE_ADDR', None) return self.cache_format % { - 'class': self.__class__.__name__, 'scope': self.scope, 'ident': ident } @@ -181,11 +179,13 @@ class ScopedRateThrottle(SimpleRateThottle): user id of the request, and the scope of the view being accessed. """ + scope_attr = 'throttle_scope' + def __init__(self, view): """ Scope is determined from the view being accessed. """ - self.scope = getattr(self.view, 'throttle_scope', None) + self.scope = getattr(self.view, self.scope_attr, None) super(ScopedRateThrottle, self).__init__(view) def parse_rate_description(self, rate): @@ -204,7 +204,7 @@ class ScopedRateThrottle(SimpleRateThottle): with the '.throttle_scope` property of the view. """ if not self.scope: - return None # Only throttle views with `.throttle_scope` set. + return None # Only throttle views if `.throttle_scope` is set. if request.user.is_authenticated(): ident = request.user.id @@ -212,7 +212,6 @@ class ScopedRateThrottle(SimpleRateThottle): ident = request.META.get('REMOTE_ADDR', None) return self.cache_format % { - 'class': self.__class__.__name__, 'scope': self.scope, 'ident': ident } diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index 0856183b4..d1e34dcda 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -83,6 +83,29 @@ The allowed request rate is determined from one of the following (in order of pr * The `rate` property on the class, which may be provided by overriding `UserThrottle` and setting the property. * The `DEFAULT_THROTTLE_RATES['user']` setting. +An API may have multiple `UserRateThrottles` in place at the same time. To do so, override `UserRateThrottle` and set a unique "scope" for each class. + +For example, multiple user throttle rates could be implemented by using the following classes... + + class BurstRateThrottle(UserRateThrottle): + scope = 'burst' + + class SustainedRateThrottle(UserRateThrottle): + scope = 'sustained' + +...and the following settings. + + API_SETTINGS = { + 'DEFAULT_THROTTLES': ( + 'example.throttles.BurstRateThrottle', + 'example.throttles.SustainedRateThrottle', + ) + 'DEFAULT_THROTTLE_RATES': { + 'burst': '60/min', + 'sustained': '1000/day' + } + } + `UserThrottle` is suitable if you want a simple global rate restriction per-user. ## ScopedRateThrottle