aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/negotiation.py33
-rw-r--r--rest_framework/request.py2
-rw-r--r--rest_framework/tests/negotiation.py10
-rw-r--r--rest_framework/views.py8
4 files changed, 24 insertions, 29 deletions
diff --git a/rest_framework/negotiation.py b/rest_framework/negotiation.py
index 8b22f669..444f8056 100644
--- a/rest_framework/negotiation.py
+++ b/rest_framework/negotiation.py
@@ -4,45 +4,34 @@ from rest_framework.utils.mediatypes import order_by_precedence, media_type_matc
class BaseContentNegotiation(object):
- def negotiate(self, request, renderers, format=None, force=False):
- raise NotImplementedError('.negotiate() must be implemented')
+ def select_parser(self, request, parsers):
+ raise NotImplementedError('.select_parser() must be implemented')
+ def select_renderer(self, request, renderers, format_suffix=None):
+ raise NotImplementedError('.select_renderer() must be implemented')
-class DefaultContentNegotiation(object):
+
+class DefaultContentNegotiation(BaseContentNegotiation):
settings = api_settings
- def select_parser(self, parsers, media_type):
+ def select_parser(self, request, parsers):
"""
Given a list of parsers and a media type, return the appropriate
parser to handle the incoming request.
"""
for parser in parsers:
- if media_type_matches(parser.media_type, media_type):
+ if media_type_matches(parser.media_type, request.content_type):
return parser
return None
- def negotiate(self, request, renderers, format=None, force=False):
+ def select_renderer(self, request, renderers, format_suffix=None):
"""
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.unforced_negotiate(request, renderers, format)
- except (exceptions.InvalidFormat, exceptions.NotAcceptable):
- if force:
- return (renderers[0], renderers[0].media_type)
- raise
-
- def unforced_negotiate(self, request, renderers, format=None):
- """
- As `.negotiate()`, but does not take the optional `force` agument,
- or suppress exceptions.
"""
# Allow URL style format override. eg. "?format=json
- format = format or request.GET.get(self.settings.URL_FORMAT_OVERRIDE)
+ format_query_param = self.settings.URL_FORMAT_OVERRIDE
+ format = format_suffix or request.GET.get(format_query_param)
if format:
renderers = self.filter_renderers(renderers, format)
diff --git a/rest_framework/request.py b/rest_framework/request.py
index b9d55de4..b212680f 100644
--- a/rest_framework/request.py
+++ b/rest_framework/request.py
@@ -266,7 +266,7 @@ class Request(object):
if stream is None or media_type is None:
return (None, None)
- parser = self.negotiator.select_parser(self.parsers, media_type)
+ parser = self.negotiator.select_parser(self, self.parsers)
if not parser:
raise exceptions.UnsupportedMediaType(media_type)
diff --git a/rest_framework/tests/negotiation.py b/rest_framework/tests/negotiation.py
index d8265b43..e06354ea 100644
--- a/rest_framework/tests/negotiation.py
+++ b/rest_framework/tests/negotiation.py
@@ -18,20 +18,20 @@ class TestAcceptedMediaType(TestCase):
self.renderers = [MockJSONRenderer(), MockHTMLRenderer()]
self.negotiator = DefaultContentNegotiation()
- def negotiate(self, request):
- return self.negotiator.negotiate(request, self.renderers)
+ def select_renderer(self, request):
+ return self.negotiator.select_renderer(request, self.renderers)
def test_client_without_accept_use_renderer(self):
request = factory.get('/')
- accepted_renderer, accepted_media_type = self.negotiate(request)
+ accepted_renderer, accepted_media_type = self.select_renderer(request)
self.assertEquals(accepted_media_type, 'application/json')
def test_client_underspecifies_accept_use_renderer(self):
request = factory.get('/', HTTP_ACCEPT='*/*')
- accepted_renderer, accepted_media_type = self.negotiate(request)
+ accepted_renderer, accepted_media_type = self.select_renderer(request)
self.assertEquals(accepted_media_type, 'application/json')
def test_client_overspecifies_accept_use_client(self):
request = factory.get('/', HTTP_ACCEPT='application/json; indent=8')
- accepted_renderer, accepted_media_type = self.negotiate(request)
+ accepted_renderer, accepted_media_type = self.select_renderer(request)
self.assertEquals(accepted_media_type, 'application/json; indent=8')
diff --git a/rest_framework/views.py b/rest_framework/views.py
index 066c0bb9..357d8939 100644
--- a/rest_framework/views.py
+++ b/rest_framework/views.py
@@ -238,7 +238,13 @@ class APIView(View):
"""
renderers = self.get_renderers()
conneg = self.get_content_negotiator()
- return conneg.negotiate(request, renderers, self.format_kwarg, force)
+
+ try:
+ return conneg.select_renderer(request, renderers, self.format_kwarg)
+ except:
+ if force:
+ return (renderers[0], renderers[0].media_type)
+ raise
def has_permission(self, request, obj=None):
"""