diff options
Diffstat (limited to 'djangorestframework/views.py')
| -rw-r--r-- | djangorestframework/views.py | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/djangorestframework/views.py b/djangorestframework/views.py index 3f0138d8..9796b362 100644 --- a/djangorestframework/views.py +++ b/djangorestframework/views.py @@ -18,7 +18,7 @@ from djangorestframework.compat import View as _View, apply_markdown from djangorestframework.response import Response from djangorestframework.request import Request from djangorestframework.settings import api_settings -from djangorestframework import parsers, authentication, permissions, status, exceptions, mixins +from djangorestframework import parsers, authentication, status, exceptions, mixins __all__ = ( @@ -86,7 +86,12 @@ class APIView(_View): List of all authenticating methods to attempt. """ - permission_classes = (permissions.FullAnonAccess,) + throttle_classes = () + """ + List of all throttles to check. + """ + + permission_classes = () """ List of all permissions that must be checked. """ @@ -195,12 +200,27 @@ class APIView(_View): """ return [permission(self) for permission in self.permission_classes] - def check_permissions(self, user): + def get_throttles(self): """ - Check user permissions and either raise an ``ImmediateResponse`` or return. + Instantiates and returns the list of thottles that this view requires. + """ + return [throttle(self) for throttle in self.throttle_classes] + + def check_permissions(self, request, obj=None): + """ + Check user permissions and either raise an ``PermissionDenied`` or return. """ for permission in self.get_permissions(): - permission.check_permission(user) + if not permission.check_permission(request, obj): + raise exceptions.PermissionDenied() + + def check_throttles(self, request): + """ + Check throttles and either raise a `Throttled` exception or return. + """ + for throttle in self.get_throttles(): + if not throttle.check_throttle(request): + raise exceptions.Throttled(throttle.wait()) def initial(self, request, *args, **kargs): """ @@ -232,6 +252,9 @@ class APIView(_View): Handle any exception that occurs, by returning an appropriate response, or re-raising the error. """ + if isinstance(exc, exceptions.Throttled): + self.headers['X-Throttle-Wait-Seconds'] = '%d' % exc.wait + if isinstance(exc, exceptions.APIException): return Response({'detail': exc.detail}, status=exc.status_code) elif isinstance(exc, Http404): @@ -255,8 +278,9 @@ class APIView(_View): try: self.initial(request, *args, **kwargs) - # check that user has the relevant permissions - self.check_permissions(request.user) + # Check that the request is allowed + self.check_permissions(request) + self.check_throttles(request) # Get the appropriate handler method if request.method.lower() in self.http_method_names: @@ -283,11 +307,12 @@ class BaseView(APIView): serializer_class = None def get_serializer(self, data=None, files=None, instance=None): + # TODO: add support for files context = { 'request': self.request, 'format': self.kwargs.get('format', None) } - return self.serializer_class(data, context=context) + return self.serializer_class(data, instance=instance, context=context) class MultipleObjectBaseView(MultipleObjectMixin, BaseView): @@ -301,7 +326,13 @@ class SingleObjectBaseView(SingleObjectMixin, BaseView): """ Base class for generic views onto a model instance. """ - pass + + def get_object(self): + """ + Override default to add support for object-level permissions. + """ + super(self, SingleObjectBaseView).get_object() + self.check_permissions(self.request, self.object) # Concrete view classes that provide method handlers |
