Commit db0b0103 by Sébastien Piquemal

made suggested fixes

parent 2cdff1b0
...@@ -43,7 +43,6 @@ class RequestMixin(object): ...@@ -43,7 +43,6 @@ class RequestMixin(object):
parser_classes = () parser_classes = ()
""" """
The set of parsers that the view can handle. The set of parsers that the view can handle.
Should be a tuple/list of classes as described in the :mod:`parsers` module. Should be a tuple/list of classes as described in the :mod:`parsers` module.
""" """
...@@ -54,22 +53,18 @@ class RequestMixin(object): ...@@ -54,22 +53,18 @@ class RequestMixin(object):
def get_parsers(self): def get_parsers(self):
""" """
Instantiates and returns the list of parsers that will be used by the request Instantiates and returns the list of parsers the request will use.
to parse its content.
""" """
if not hasattr(self, '_parsers'): return [p(self) for p in self.parser_classes]
self._parsers = [p(self) for p in self.parser_classes]
return self._parsers
def prepare_request(self, request): def create_request(self, request):
""" """
Prepares the request cycle. Returns an instance of :class:`request.Request`, Creates and returns an instance of :class:`request.Request`.
wrapping the original request object. This new instance wraps the `request` passed as a parameter, and use the
parsers set on the view.
""" """
parsers = self.get_parsers() parsers = self.get_parsers()
request = self.request_class(request, parsers=parsers) return self.request_class(request, parsers=parsers)
self.request = request
return request
@property @property
def _parsed_media_types(self): def _parsed_media_types(self):
...@@ -89,38 +84,29 @@ class ResponseMixin(object): ...@@ -89,38 +84,29 @@ class ResponseMixin(object):
renderer_classes = () renderer_classes = ()
""" """
The set of response renderers that the view can handle. The set of response renderers that the view can handle.
Should be a tuple/list of classes as described in the :mod:`renderers` module. Should be a tuple/list of classes as described in the :mod:`renderers` module.
""" """
def get_renderers(self): def get_renderers(self):
""" """
Instantiates and returns the list of renderers that will be used to render Instantiates and returns the list of renderers the response will use.
the response.
""" """
if not hasattr(self, '_renderers'): return [r(self) for r in self.renderer_classes]
self._renderers = [r(self) for r in self.renderer_classes]
return self._renderers
def prepare_response(self, response): def prepare_response(self, response):
""" """
Prepares and returns `response`. Prepares and returns `response`.
This has no effect if the response is not an instance of :class:`response.Response`. This has no effect if the response is not an instance of :class:`response.Response`.
""" """
if hasattr(response, 'request') and response.request is None: if hasattr(response, 'request') and response.request is None:
response.request = self.request response.request = self.request
# Always add these headers. # set all the cached headers
response['Allow'] = ', '.join(allowed_methods(self))
# sample to allow caching using Vary http header
response['Vary'] = 'Authenticate, Accept'
# merge with headers possibly set at some point in the view
for name, value in self.headers.items(): for name, value in self.headers.items():
response[name] = value response[name] = value
# set the views renderers on the response # set the views renderers on the response
response.renderers = self.get_renderers() response.renderers = self.get_renderers()
self.response = response
return response return response
@property @property
...@@ -571,12 +557,12 @@ class PaginatorMixin(object): ...@@ -571,12 +557,12 @@ class PaginatorMixin(object):
page_num = int(self.request.GET.get('page', '1')) page_num = int(self.request.GET.get('page', '1'))
except ValueError: except ValueError:
raise ImmediateResponse( raise ImmediateResponse(
content={'detail': 'That page contains no results'}, {'detail': 'That page contains no results'},
status=status.HTTP_404_NOT_FOUND) status=status.HTTP_404_NOT_FOUND)
if page_num not in paginator.page_range: if page_num not in paginator.page_range:
raise ImmediateResponse( raise ImmediateResponse(
content={'detail': 'That page contains no results'}, {'detail': 'That page contains no results'},
status=status.HTTP_404_NOT_FOUND) status=status.HTTP_404_NOT_FOUND)
page = paginator.page(page_num) page = paginator.page(page_num)
......
...@@ -89,7 +89,7 @@ class JSONParser(BaseParser): ...@@ -89,7 +89,7 @@ class JSONParser(BaseParser):
return (json.load(stream), None) return (json.load(stream), None)
except ValueError, exc: except ValueError, exc:
raise ImmediateResponse( raise ImmediateResponse(
content={'detail': 'JSON parse error - %s' % unicode(exc)}, {'detail': 'JSON parse error - %s' % unicode(exc)},
status=status.HTTP_400_BAD_REQUEST) status=status.HTTP_400_BAD_REQUEST)
...@@ -112,7 +112,7 @@ if yaml: ...@@ -112,7 +112,7 @@ if yaml:
return (yaml.safe_load(stream), None) return (yaml.safe_load(stream), None)
except ValueError, exc: except ValueError, exc:
raise ImmediateResponse( raise ImmediateResponse(
content={'detail': 'YAML parse error - %s' % unicode(exc)}, {'detail': 'YAML parse error - %s' % unicode(exc)},
status=status.HTTP_400_BAD_REQUEST) status=status.HTTP_400_BAD_REQUEST)
else: else:
YAMLParser = None YAMLParser = None
...@@ -172,7 +172,7 @@ class MultiPartParser(BaseParser): ...@@ -172,7 +172,7 @@ class MultiPartParser(BaseParser):
django_parser = DjangoMultiPartParser(self.view.request.META, stream, upload_handlers) django_parser = DjangoMultiPartParser(self.view.request.META, stream, upload_handlers)
except MultiPartParserError, exc: except MultiPartParserError, exc:
raise ImmediateResponse( raise ImmediateResponse(
content={'detail': 'multipart parse error - %s' % unicode(exc)}, {'detail': 'multipart parse error - %s' % unicode(exc)},
status=status.HTTP_400_BAD_REQUEST) status=status.HTTP_400_BAD_REQUEST)
return django_parser.parse() return django_parser.parse()
......
...@@ -22,12 +22,12 @@ __all__ = ( ...@@ -22,12 +22,12 @@ __all__ = (
_403_FORBIDDEN_RESPONSE = ImmediateResponse( _403_FORBIDDEN_RESPONSE = ImmediateResponse(
content={'detail': 'You do not have permission to access this resource. ' + {'detail': 'You do not have permission to access this resource. ' +
'You may need to login or otherwise authenticate the request.'}, 'You may need to login or otherwise authenticate the request.'},
status=status.HTTP_403_FORBIDDEN) status=status.HTTP_403_FORBIDDEN)
_503_SERVICE_UNAVAILABLE = ImmediateResponse( _503_SERVICE_UNAVAILABLE = ImmediateResponse(
content={'detail': 'request was throttled'}, {'detail': 'request was throttled'},
status=status.HTTP_503_SERVICE_UNAVAILABLE) status=status.HTTP_503_SERVICE_UNAVAILABLE)
......
...@@ -166,9 +166,9 @@ class Request(object): ...@@ -166,9 +166,9 @@ class Request(object):
if parser.can_handle_request(content_type): if parser.can_handle_request(content_type):
return parser.parse(stream) return parser.parse(stream)
raise ImmediateResponse(content={'error': raise ImmediateResponse({
'Unsupported media type in request \'%s\'.' % content_type}, 'error': 'Unsupported media type in request \'%s\'.' % content_type},
status=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE) status=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE)
@property @property
def _parsed_media_types(self): def _parsed_media_types(self):
......
...@@ -174,7 +174,7 @@ class FormResource(Resource): ...@@ -174,7 +174,7 @@ class FormResource(Resource):
detail[u'field_errors'] = field_errors detail[u'field_errors'] = field_errors
# Return HTTP 400 response (BAD REQUEST) # Return HTTP 400 response (BAD REQUEST)
raise ImmediateResponse(content=detail, status=400) raise ImmediateResponse(detail, status=400)
def get_form_class(self, method=None): def get_form_class(self, method=None):
""" """
......
...@@ -125,7 +125,7 @@ class Response(SimpleTemplateResponse): ...@@ -125,7 +125,7 @@ class Response(SimpleTemplateResponse):
return renderer, media_type return renderer, media_type
# No acceptable renderers were found # No acceptable renderers were found
raise ImmediateResponse(content={'detail': 'Could not satisfy the client\'s Accept header', raise ImmediateResponse({'detail': 'Could not satisfy the client\'s Accept header',
'available_types': self._rendered_media_types}, 'available_types': self._rendered_media_types},
status=status.HTTP_406_NOT_ACCEPTABLE, status=status.HTTP_406_NOT_ACCEPTABLE,
renderers=self.renderers) renderers=self.renderers)
......
...@@ -173,7 +173,7 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): ...@@ -173,7 +173,7 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
""" """
Return an HTTP 405 error if an operation is called which does not have a handler method. Return an HTTP 405 error if an operation is called which does not have a handler method.
""" """
raise ImmediateResponse(content= raise ImmediateResponse(
{'detail': 'Method \'%s\' not allowed on this resource.' % request.method}, {'detail': 'Method \'%s\' not allowed on this resource.' % request.method},
status=status.HTTP_405_METHOD_NOT_ALLOWED) status=status.HTTP_405_METHOD_NOT_ALLOWED)
...@@ -199,6 +199,12 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): ...@@ -199,6 +199,12 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
""" """
# Restore script_prefix. # Restore script_prefix.
set_script_prefix(self.orig_prefix) set_script_prefix(self.orig_prefix)
# Always add these headers.
response['Allow'] = ', '.join(allowed_methods(self))
# sample to allow caching using Vary http header
response['Vary'] = 'Authenticate, Accept'
return response return response
# Note: session based authentication is explicitly CSRF validated, # Note: session based authentication is explicitly CSRF validated,
...@@ -211,7 +217,7 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): ...@@ -211,7 +217,7 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
try: try:
# Get a custom request, built form the original request instance # Get a custom request, built form the original request instance
request = self.prepare_request(request) self.request = request = self.create_request(request)
# `initial` is the opportunity to temper with the request, # `initial` is the opportunity to temper with the request,
# even completely replace it. # even completely replace it.
...@@ -230,7 +236,7 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): ...@@ -230,7 +236,7 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
response = handler(request, *args, **kwargs) response = handler(request, *args, **kwargs)
# Prepare response for the response cycle. # Prepare response for the response cycle.
response = self.prepare_response(response) self.response = response = self.prepare_response(response)
# Pre-serialize filtering (eg filter complex objects into natively serializable types) # Pre-serialize filtering (eg filter complex objects into natively serializable types)
# TODO: ugly hack to handle both HttpResponse and Response. # TODO: ugly hack to handle both HttpResponse and Response.
...@@ -241,7 +247,7 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): ...@@ -241,7 +247,7 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
except ImmediateResponse, response: except ImmediateResponse, response:
# Prepare response for the response cycle. # Prepare response for the response cycle.
self.prepare_response(response) self.response = response = self.prepare_response(response)
# `final` is the last opportunity to temper with the response, or even # `final` is the last opportunity to temper with the response, or even
# completely replace it. # completely replace it.
...@@ -260,10 +266,7 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): ...@@ -260,10 +266,7 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
for name, field in form.fields.iteritems(): for name, field in form.fields.iteritems():
field_name_types[name] = field.__class__.__name__ field_name_types[name] = field.__class__.__name__
content['fields'] = field_name_types content['fields'] = field_name_types
# Note 'ImmediateResponse' is misleading, it's just any response raise ImmediateResponse(content, status=status.HTTP_200_OK)
# that should be rendered and returned immediately, without any
# response filtering.
raise ImmediateResponse(content=content, status=status.HTTP_200_OK)
class ModelView(View): class ModelView(View):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment