diff options
Diffstat (limited to 'djangorestframework/contentnegotiation.py')
| -rw-r--r-- | djangorestframework/contentnegotiation.py | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/djangorestframework/contentnegotiation.py b/djangorestframework/contentnegotiation.py index 223919ef..1c646ca7 100644 --- a/djangorestframework/contentnegotiation.py +++ b/djangorestframework/contentnegotiation.py @@ -1,24 +1,40 @@ from djangorestframework import exceptions from djangorestframework.settings import api_settings from djangorestframework.utils.mediatypes import order_by_precedence +from django.http import Http404 import re MSIE_USER_AGENT_REGEX = re.compile(r'^Mozilla/[0-9]+\.[0-9]+ \([^)]*; MSIE [0-9]+\.[0-9]+[a-z]?;[^)]*\)(?!.* Opera )') class BaseContentNegotiation(object): - def determine_renderer(self, request, renderers): - raise NotImplementedError('.determine_renderer() must be implemented') + def negotiate(self, request, renderers, format=None, force=False): + raise NotImplementedError('.negotiate() must be implemented') class DefaultContentNegotiation(object): settings = api_settings - def negotiate(self, request, renderers): + def negotiate(self, request, renderers, format=None, force=False): """ Given a request and a list of renderers, return a two-tuple of: (renderer, media type). + + If force is set, then suppress exceptions, and forcibly return a + fallback renderer and media_type. + """ + try: + return self._negotiate(request, renderers, format) + except (Http404, exceptions.NotAcceptable): + if force: + return (renderers[0], renderers[0].media_type) + raise + + def _negotiate(self, request, renderers, format=None): + """ + Actual implementation of negotiate, inside the 'force' wrapper. """ + renderers = self.filter_renderers(renderers, format) accepts = self.get_accept_list(request) # Check the acceptable media types against each renderer, @@ -33,6 +49,19 @@ class DefaultContentNegotiation(object): raise exceptions.NotAcceptable(available_renderers=renderers) + def filter_renderers(self, renderers, format): + """ + If there is a '.json' style format suffix, only use + renderers that accept that format. + """ + if not format: + return renderers + + renderers = [renderer for renderer in renderers + if renderer.can_handle_format(format)] + if not renderers: + raise Http404() + def get_accept_list(self, request): """ Given the incoming request, return a tokenised list of |
