diff --git a/djangorestframework/modelresource.py b/djangorestframework/modelresource.py index 24fb62ab8..a91c79ee6 100644 --- a/djangorestframework/modelresource.py +++ b/djangorestframework/modelresource.py @@ -341,6 +341,19 @@ class ModelResource(Resource): return _any(data, self.fields) + def get(self, request, *args, **kwargs): + try: + if args: + # If we have any none kwargs then assume the last represents the primrary key + instance = self.model.objects.get(pk=args[-1], **kwargs) + else: + # Otherwise assume the kwargs uniquely identify the model + instance = self.model.objects.get(**kwargs) + except self.model.DoesNotExist: + raise ErrorResponse(status.HTTP_404_NOT_FOUND) + + return instance + def post(self, request, *args, **kwargs): # TODO: test creation on a non-existing resource url @@ -361,19 +374,6 @@ class ModelResource(Resource): headers['Location'] = instance.get_absolute_url() return Response(status.HTTP_201_CREATED, instance, headers) - def get(self, request, *args, **kwargs): - try: - if args: - # If we have any none kwargs then assume the last represents the primrary key - instance = self.model.objects.get(pk=args[-1], **kwargs) - else: - # Otherwise assume the kwargs uniquely identify the model - instance = self.model.objects.get(**kwargs) - except self.model.DoesNotExist: - raise ErrorResponse(status.HTTP_404_NOT_FOUND) - - return instance - def put(self, request, *args, **kwargs): # TODO: update on the url of a non-existing resource url doesn't work correctly at the moment - will end up with a new url try: diff --git a/djangorestframework/resource.py b/djangorestframework/resource.py index 55a9b57d9..65aa09c64 100644 --- a/djangorestframework/resource.py +++ b/djangorestframework/resource.py @@ -16,8 +16,8 @@ __all__ = ['Resource'] class Resource(RequestMixin, ResponseMixin, AuthMixin, View): - """Handles incoming requests and maps them to REST operations, - performing authentication, input deserialization, input validation, output serialization.""" + """Handles incoming requests and maps them to REST operations. + Performs request deserialization, response serialization, authentication and input validation.""" http_method_names = ['get', 'post', 'put', 'delete', 'head', 'options', 'trace', 'patch'] @@ -73,68 +73,55 @@ class Resource(RequestMixin, ResponseMixin, AuthMixin, View): return data - # Session based authentication is explicitly CSRF validated, all other authentication is CSRF exempt. + # Note: session based authentication is explicitly CSRF validated, + # all other authentication is CSRF exempt. @csrf_exempt def dispatch(self, request, *args, **kwargs): - """This method is the core of Resource, through which all requests are passed. + self.request = request + self.args = args + self.kwargs = kwargs - Broadly this consists of the following procedure: + # Calls to 'reverse' will not be fully qualified unless we set the scheme/host/port here. + prefix = '%s://%s' % (request.is_secure() and 'https' or 'http', request.get_host()) + set_script_prefix(prefix) - 0. ensure the operation is permitted - 1. deserialize request content into request data, using standard HTTP content types (PUT/POST only) - 2. cleanup and validate request data (PUT/POST only) - 3. call the core method to get the response data - 4. cleanup the response data - 5. serialize response data into response content, using standard HTTP content negotiation - """ try: - self.request = request - self.args = args - self.kwargs = kwargs - - # Calls to 'reverse' will not be fully qualified unless we set the scheme/host/port here. - prefix = '%s://%s' % (request.is_secure() and 'https' or 'http', request.get_host()) - set_script_prefix(prefix) - - try: - # If using a form POST with '_method'/'_content'/'_content_type' overrides, then alter - # self.method, self.content_type, self.RAW_CONTENT & self.CONTENT appropriately. - self.perform_form_overloading() - - # Authenticate and check request is has the relevant permissions - self.check_permissions() - - # Get the appropriate handler method - if self.method.lower() in self.http_method_names: - handler = getattr(self, self.method.lower(), self.http_method_not_allowed) - else: - handler = self.http_method_not_allowed - - response_obj = handler(request, *args, **kwargs) - - # Allow return value to be either Response, or an object, or None - if isinstance(response_obj, Response): - response = response_obj - elif response_obj is not None: - response = Response(status.HTTP_200_OK, response_obj) - else: - response = Response(status.HTTP_204_NO_CONTENT) - - # Pre-serialize filtering (eg filter complex objects into natively serializable types) - response.cleaned_content = self.cleanup_response(response.raw_content) - - except ErrorResponse, exc: - response = exc.response - - # Always add these headers. - # - # TODO - this isn't actually the correct way to set the vary header, - # also it's currently sub-obtimal for HTTP caching - need to sort that out. - response.headers['Allow'] = ', '.join(self.allowed_methods) - response.headers['Vary'] = 'Authenticate, Accept' - - return self.emit(response) - except: - import traceback - traceback.print_exc() + # If using a form POST with '_method'/'_content'/'_content_type' overrides, then alter + # self.method, self.content_type, self.RAW_CONTENT & self.CONTENT appropriately. + self.perform_form_overloading() + + # Authenticate and check request is has the relevant permissions + self.check_permissions() + + # Get the appropriate handler method + if self.method.lower() in self.http_method_names: + handler = getattr(self, self.method.lower(), self.http_method_not_allowed) + else: + handler = self.http_method_not_allowed + + response_obj = handler(request, *args, **kwargs) + + # Allow return value to be either Response, or an object, or None + if isinstance(response_obj, Response): + response = response_obj + elif response_obj is not None: + response = Response(status.HTTP_200_OK, response_obj) + else: + response = Response(status.HTTP_204_NO_CONTENT) + + # Pre-serialize filtering (eg filter complex objects into natively serializable types) + response.cleaned_content = self.cleanup_response(response.raw_content) + + except ErrorResponse, exc: + response = exc.response + + # Always add these headers. + # + # TODO - this isn't actually the correct way to set the vary header, + # also it's currently sub-obtimal for HTTP caching - need to sort that out. + response.headers['Allow'] = ', '.join(self.allowed_methods) + response.headers['Vary'] = 'Authenticate, Accept' + + return self.emit(response) +