tidy up last bits of renderer media type handling

This commit is contained in:
Tom Christie 2011-05-24 16:31:17 +01:00
parent ce6e5fdc01
commit 894bf34451
3 changed files with 59 additions and 60 deletions

View File

@ -243,21 +243,24 @@ class ResponseMixin(object):
self.response = response self.response = response
try: try:
renderer = self._determine_renderer(self.request) renderer, media_type = self._determine_renderer(self.request)
except ErrorResponse, exc: except ErrorResponse, exc:
renderer = self._default_renderer(self) renderer = self._default_renderer(self)
media_type = renderer.media_type
response = exc.response response = exc.response
# Set the media type of the response
# Note that the renderer *could* override it in .render() if required.
response.media_type = renderer.media_type
# Serialize the response content # Serialize the response content
# TODO: renderer.media_type isn't the right thing to do here...
if response.has_content_body: if response.has_content_body:
content = renderer.render(response.cleaned_content, renderer.media_type) content = renderer.render(response.cleaned_content, media_type)
else: else:
content = renderer.render() content = renderer.render()
# Build the HTTP Response # Build the HTTP Response
# TODO: renderer.media_type isn't the right thing to do here... resp = HttpResponse(content, mimetype=response.media_type, status=response.status)
resp = HttpResponse(content, mimetype=renderer.media_type, status=response.status)
for (key, val) in response.headers.items(): for (key, val) in response.headers.items():
resp[key] = val resp[key] = val
@ -266,8 +269,10 @@ class ResponseMixin(object):
def _determine_renderer(self, request): def _determine_renderer(self, request):
""" """
Return the appropriate renderer for the output, given the client's 'Accept' header, Determines the appropriate renderer for the output, given the client's 'Accept' header,
and the content types that this mixin knows how to serve. and the :attr:`renderers` set on this class.
Returns a 2-tuple of `(renderer, media_type)`
See: RFC 2616, Section 14 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html See: RFC 2616, Section 14 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
""" """
@ -285,19 +290,19 @@ class ResponseMixin(object):
accept_list = [token.strip() for token in request.META["HTTP_ACCEPT"].split(',')] accept_list = [token.strip() for token in request.META["HTTP_ACCEPT"].split(',')]
else: else:
# No accept header specified # No accept header specified
return self._default_renderer(self) return (self._default_renderer(self), self._default_renderer.media_type)
# Check the acceptable media types against each renderer, # Check the acceptable media types against each renderer,
# attempting more specific media types first # attempting more specific media types first
# NB. The inner loop here isn't as bad as it first looks :) # NB. The inner loop here isn't as bad as it first looks :)
# We're effectivly looping over max len(accept_list) * len(self.renderers) # Worst case is we're looping over len(accept_list) * len(self.renderers)
renderers = [renderer_cls(self) for renderer_cls in self.renderers] renderers = [renderer_cls(self) for renderer_cls in self.renderers]
for media_type_lst in order_by_precedence(accept_list): for media_type_lst in order_by_precedence(accept_list):
for renderer in renderers: for renderer in renderers:
for media_type in media_type_lst: for media_type in media_type_lst:
if renderer.can_handle_response(media_type): if renderer.can_handle_response(media_type):
return renderer return renderer, media_type
# No acceptable renderers were found # No acceptable renderers were found
raise ErrorResponse(status.HTTP_406_NOT_ACCEPTABLE, raise ErrorResponse(status.HTTP_406_NOT_ACCEPTABLE,

View File

@ -18,6 +18,7 @@ class Response(object):
def __init__(self, status=200, content=None, headers={}): def __init__(self, status=200, content=None, headers={}):
self.status = status self.status = status
self.media_type = None
self.has_content_body = content is not None self.has_content_body = content is not None
self.raw_content = content # content prior to filtering self.raw_content = content # content prior to filtering
self.cleaned_content = content # content after filtering self.cleaned_content = content # content after filtering

View File

@ -99,7 +99,6 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
# all other authentication is CSRF exempt. # all other authentication is CSRF exempt.
@csrf_exempt @csrf_exempt
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
try:
self.request = request self.request = request
self.args = args self.args = args
self.kwargs = kwargs self.kwargs = kwargs
@ -147,12 +146,6 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
return self.render(response) return self.render(response)
except:
import traceback
traceback.print_exc()
raise
class ModelView(View): class ModelView(View):
"""A RESTful view that maps to a model in the database.""" """A RESTful view that maps to a model in the database."""