diff options
Diffstat (limited to 'djangorestframework/views.py')
| -rw-r--r-- | djangorestframework/views.py | 65 |
1 files changed, 43 insertions, 22 deletions
diff --git a/djangorestframework/views.py b/djangorestframework/views.py index 9debee19..32d403ea 100644 --- a/djangorestframework/views.py +++ b/djangorestframework/views.py @@ -54,11 +54,14 @@ def _camelcase_to_spaces(content): class APIView(_View): + settings = api_settings + renderer_classes = api_settings.DEFAULT_RENDERERS parser_classes = api_settings.DEFAULT_PARSERS authentication_classes = api_settings.DEFAULT_AUTHENTICATION throttle_classes = api_settings.DEFAULT_THROTTLES permission_classes = api_settings.DEFAULT_PERMISSIONS + content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION @classmethod def as_view(cls, **initkwargs): @@ -169,6 +172,19 @@ class APIView(_View): """ return self.renderer_classes[0] + def get_format_suffix(self, **kwargs): + """ + Determine if the request includes a '.json' style format suffix + """ + if self.settings.FORMAT_SUFFIX_KWARG: + return kwargs.get(self.settings.FORMAT_SUFFIX_KWARG) + + def get_renderers(self, format=None): + """ + Instantiates and returns the list of renderers that this view can use. + """ + return [renderer(self) for renderer in self.renderer_classes] + def get_permissions(self): """ Instantiates and returns the list of permissions that this view requires. @@ -177,10 +193,18 @@ class APIView(_View): def get_throttles(self): """ - Instantiates and returns the list of thottles that this view requires. + Instantiates and returns the list of thottles that this view uses. """ return [throttle(self) for throttle in self.throttle_classes] + def content_negotiation(self, request, force=False): + """ + Determine which renderer and media type to use render the response. + """ + renderers = self.get_renderers() + conneg = self.content_negotiation_class() + return conneg.negotiate(request, renderers, self.format, force) + def check_permissions(self, request, obj=None): """ Check if request should be permitted. @@ -204,35 +228,37 @@ class APIView(_View): return Request(request, parser_classes=self.parser_classes, authentication_classes=self.authentication_classes) + def initial(self, request, *args, **kwargs): + """ + Runs anything that needs to occur prior to calling the method handlers. + """ + self.format = self.get_format_suffix(**kwargs) + self.check_permissions(request) + self.check_throttles(request) + self.renderer, self.media_type = self.content_negotiation(request) + def finalize_response(self, request, response, *args, **kwargs): """ Returns the final response object. """ if isinstance(response, Response): - response.view = self - response.request = request - response.renderer_classes = self.renderer_classes - if api_settings.FORMAT_SUFFIX_KWARG: - response.format = kwargs.get(api_settings.FORMAT_SUFFIX_KWARG, None) + if not getattr(self, 'renderer', None): + self.renderer, self.media_type = self.content_negotiation(request, force=True) + response.renderer = self.renderer + response.media_type = self.media_type for key, value in self.headers.items(): response[key] = value return response - def initial(self, request, *args, **kwargs): - """ - Runs anything that needs to occur prior to calling the method handlers. - """ - self.check_permissions(request) - self.check_throttles(request) - def handle_exception(self, exc): """ Handle any exception that occurs, by returning an appropriate response, or re-raising the error. """ if isinstance(exc, exceptions.Throttled): + # Throttle wait header self.headers['X-Throttle-Wait-Seconds'] = '%d' % exc.wait if isinstance(exc, exceptions.APIException): @@ -250,14 +276,8 @@ class APIView(_View): @csrf_exempt def dispatch(self, request, *args, **kwargs): """ - `APIView.dispatch()` is pretty much the same as Django's regular - `View.dispatch()`, except that it includes hooks to: - - * Initialize the request object. - * Finalize the response object. - * Handle exceptions that occur in the handler method. - * An initial hook for code such as permission checking that should - occur prior to running the method handlers. + `.dispatch()` is pretty much the same as Django's regular dispatch, + but with extra hooks for startup, finalize, and exception handling. """ request = self.initialize_request(request, *args, **kwargs) self.request = request @@ -270,7 +290,8 @@ class APIView(_View): # Get the appropriate handler method if request.method.lower() in self.http_method_names: - handler = getattr(self, request.method.lower(), self.http_method_not_allowed) + handler = getattr(self, request.method.lower(), + self.http_method_not_allowed) else: handler = self.http_method_not_allowed |
