aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Christie2012-10-10 10:02:37 +0100
committerTom Christie2012-10-10 10:02:37 +0100
commitccd2b0117d9c26199b1862a302b1eb06dd2f07b2 (patch)
tree05e47209445303f2cda704d4ac50791551ddae5b
parent900c4b625b62a6c1f4a16bfe8d6b5d77480427ff (diff)
downloaddjango-rest-framework-ccd2b0117d9c26199b1862a302b1eb06dd2f07b2.tar.bz2
Permissions and throttles no longer have a view attribute on self. Explicitly passed to .has_permissions(request, view, obj=None) / .allow_request(request, view)
-rw-r--r--docs/api-guide/permissions.md2
-rw-r--r--docs/api-guide/throttling.md4
-rw-r--r--rest_framework/permissions.py17
-rw-r--r--rest_framework/tests/renderers.py2
-rw-r--r--rest_framework/throttling.py41
-rw-r--r--rest_framework/views.py8
6 files changed, 28 insertions, 46 deletions
diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md
index 9a3c39ab..b6912d88 100644
--- a/docs/api-guide/permissions.md
+++ b/docs/api-guide/permissions.md
@@ -88,7 +88,7 @@ The `DjangoModelPermissions` class also supports object-level permissions. Thir
## Custom permissions
-To implement a custom permission, override `BasePermission` and implement the `.has_permission(self, request, obj=None)` method.
+To implement a custom permission, override `BasePermission` and implement the `.has_permission(self, request, view, obj=None)` method.
The method should return `True` if the request should be granted access, and `False` otherwise.
diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md
index 7861e9ba..0e228905 100644
--- a/docs/api-guide/throttling.md
+++ b/docs/api-guide/throttling.md
@@ -144,8 +144,8 @@ User requests to either `ContactListView` or `ContactDetailView` would be restri
## Custom throttles
-To create a custom throttle, override `BaseThrottle` and implement `.allow_request(request)`. The method should return `True` if the request should be allowed, and `False` otherwise.
+To create a custom throttle, override `BaseThrottle` and implement `.allow_request(request, view)`. The method should return `True` if the request should be allowed, and `False` otherwise.
-Optionally you may also override the `.wait()` method. If implemented, `.wait()` should return a recomended number of seconds to wait before attempting the next request, or `None`. The `.wait()` method will only be called if `.check_throttle()` has previously returned `False`.
+Optionally you may also override the `.wait()` method. If implemented, `.wait()` should return a recomended number of seconds to wait before attempting the next request, or `None`. The `.wait()` method will only be called if `.allow_request()` has previously returned `False`.
[permissions]: permissions.md
diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py
index 51837a01..13ea39ea 100644
--- a/rest_framework/permissions.py
+++ b/rest_framework/permissions.py
@@ -13,13 +13,8 @@ class BasePermission(object):
"""
A base class from which all permission classes should inherit.
"""
- def __init__(self, view):
- """
- Permission classes are always passed the current view on creation.
- """
- self.view = view
- def has_permission(self, request, obj=None):
+ def has_permission(self, request, view, obj=None):
"""
Should simply return, or raise an :exc:`response.ImmediateResponse`.
"""
@@ -31,7 +26,7 @@ class IsAuthenticated(BasePermission):
Allows access only to authenticated users.
"""
- def has_permission(self, request, obj=None):
+ def has_permission(self, request, view, obj=None):
if request.user and request.user.is_authenticated():
return True
return False
@@ -42,7 +37,7 @@ class IsAdminUser(BasePermission):
Allows access only to admin users.
"""
- def has_permission(self, request, obj=None):
+ def has_permission(self, request, view, obj=None):
if request.user and request.user.is_staff:
return True
return False
@@ -53,7 +48,7 @@ class IsAuthenticatedOrReadOnly(BasePermission):
The request is authenticated as a user, or is a read-only request.
"""
- def has_permission(self, request, obj=None):
+ def has_permission(self, request, view, obj=None):
if (request.method in SAFE_METHODS or
request.user and
request.user.is_authenticated()):
@@ -96,8 +91,8 @@ class DjangoModelPermissions(BasePermission):
}
return [perm % kwargs for perm in self.perms_map[method]]
- def has_permission(self, request, obj=None):
- model_cls = self.view.model
+ def has_permission(self, request, view, obj=None):
+ model_cls = view.model
perms = self.get_required_permissions(request.method, model_cls)
if (request.user and
diff --git a/rest_framework/tests/renderers.py b/rest_framework/tests/renderers.py
index 6de8f124..b8c30fcc 100644
--- a/rest_framework/tests/renderers.py
+++ b/rest_framework/tests/renderers.py
@@ -92,7 +92,7 @@ urlpatterns = patterns('',
class POSTDeniedPermission(permissions.BasePermission):
- def has_permission(self, request, obj=None):
+ def has_permission(self, request, view, obj=None):
return request.method != 'POST'
diff --git a/rest_framework/throttling.py b/rest_framework/throttling.py
index 0d33f0e2..566c277d 100644
--- a/rest_framework/throttling.py
+++ b/rest_framework/throttling.py
@@ -8,14 +8,7 @@ class BaseThrottle(object):
"""
Rate throttling of requests.
"""
-
- def __init__(self, view=None):
- """
- All throttles hold a reference to the instantiating view.
- """
- self.view = view
-
- def allow_request(self, request):
+ def allow_request(self, request, view):
"""
Return `True` if the request should be allowed, `False` otherwise.
"""
@@ -48,13 +41,12 @@ class SimpleRateThottle(BaseThrottle):
cache_format = 'throtte_%(scope)s_%(ident)s'
scope = None
- def __init__(self, view):
- super(SimpleRateThottle, self).__init__(view)
+ def __init__(self):
if not getattr(self, 'rate', None):
self.rate = self.get_rate()
self.num_requests, self.duration = self.parse_rate(self.rate)
- def get_cache_key(self, request):
+ def get_cache_key(self, request, view):
"""
Should return a unique cache-key which can be used for throttling.
Must be overridden.
@@ -90,7 +82,7 @@ class SimpleRateThottle(BaseThrottle):
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
return (num_requests, duration)
- def allow_request(self, request):
+ def allow_request(self, request, view):
"""
Implement the check to see if the request should be throttled.
@@ -100,7 +92,7 @@ class SimpleRateThottle(BaseThrottle):
if self.rate is None:
return True
- self.key = self.get_cache_key(request)
+ self.key = self.get_cache_key(request, view)
self.history = cache.get(self.key, [])
self.now = self.timer()
@@ -149,7 +141,7 @@ class AnonRateThrottle(SimpleRateThottle):
"""
scope = 'anon'
- def get_cache_key(self, request):
+ def get_cache_key(self, request, view):
if request.user.is_authenticated():
return None # Only throttle unauthenticated requests.
@@ -171,7 +163,7 @@ class UserRateThrottle(SimpleRateThottle):
"""
scope = 'user'
- def get_cache_key(self, request):
+ def get_cache_key(self, request, view):
if request.user.is_authenticated():
ident = request.user.id
else:
@@ -190,25 +182,20 @@ class ScopedRateThrottle(SimpleRateThottle):
throttled. The unique cache key will be generated by concatenating the
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, self.scope_attr, None)
- super(ScopedRateThrottle, self).__init__(view)
-
- def get_cache_key(self, request):
+ def get_cache_key(self, request, view):
"""
If `view.throttle_scope` is not set, don't apply this throttle.
Otherwise generate the unique cache key by concatenating the user id
with the '.throttle_scope` property of the view.
"""
- if not self.scope:
- return None # Only throttle views if `.throttle_scope` is set.
+ scope = getattr(view, self.scope_attr, None)
+
+ if not scope:
+ # Only throttle views if `.throttle_scope` is set on the view.
+ return None
if request.user.is_authenticated():
ident = request.user.id
@@ -216,6 +203,6 @@ class ScopedRateThrottle(SimpleRateThottle):
ident = request.META.get('REMOTE_ADDR', None)
return self.cache_format % {
- 'scope': self.scope,
+ 'scope': scope,
'ident': ident
}
diff --git a/rest_framework/views.py b/rest_framework/views.py
index 2c940dac..058a6cd3 100644
--- a/rest_framework/views.py
+++ b/rest_framework/views.py
@@ -189,13 +189,13 @@ class APIView(View):
"""
Instantiates and returns the list of permissions that this view requires.
"""
- return [permission(self) for permission in self.permission_classes]
+ return [permission() for permission in self.permission_classes]
def get_throttles(self):
"""
Instantiates and returns the list of thottles that this view uses.
"""
- return [throttle(self) for throttle in self.throttle_classes]
+ return [throttle() for throttle in self.throttle_classes]
def get_content_negotiator(self):
"""
@@ -220,7 +220,7 @@ class APIView(View):
Return `True` if the request should be permitted.
"""
for permission in self.get_permissions():
- if not permission.has_permission(request, obj):
+ if not permission.has_permission(request, self, obj):
return False
return True
@@ -229,7 +229,7 @@ class APIView(View):
Check if request should be throttled.
"""
for throttle in self.get_throttles():
- if not throttle.allow_request(request):
+ if not throttle.allow_request(request, self):
self.throttled(request, throttle.wait())
# Dispatch methods