This commit is contained in:
Tom Christie 2011-04-25 04:48:55 +01:00
parent 4692374e0d
commit 84a4fd3ea1
2 changed files with 61 additions and 74 deletions

View File

@ -341,6 +341,19 @@ class ModelResource(Resource):
return _any(data, self.fields) 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): def post(self, request, *args, **kwargs):
# TODO: test creation on a non-existing resource url # TODO: test creation on a non-existing resource url
@ -361,19 +374,6 @@ class ModelResource(Resource):
headers['Location'] = instance.get_absolute_url() headers['Location'] = instance.get_absolute_url()
return Response(status.HTTP_201_CREATED, instance, headers) 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): 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 # 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: try:

View File

@ -16,8 +16,8 @@ __all__ = ['Resource']
class Resource(RequestMixin, ResponseMixin, AuthMixin, View): class Resource(RequestMixin, ResponseMixin, AuthMixin, View):
"""Handles incoming requests and maps them to REST operations, """Handles incoming requests and maps them to REST operations.
performing authentication, input deserialization, input validation, output serialization.""" Performs request deserialization, response serialization, authentication and input validation."""
http_method_names = ['get', 'post', 'put', 'delete', 'head', 'options', 'trace', 'patch'] http_method_names = ['get', 'post', 'put', 'delete', 'head', 'options', 'trace', 'patch']
@ -73,68 +73,55 @@ class Resource(RequestMixin, ResponseMixin, AuthMixin, View):
return data 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 @csrf_exempt
def dispatch(self, request, *args, **kwargs): 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: try:
self.request = request # If using a form POST with '_method'/'_content'/'_content_type' overrides, then alter
self.args = args # self.method, self.content_type, self.RAW_CONTENT & self.CONTENT appropriately.
self.kwargs = kwargs self.perform_form_overloading()
# Calls to 'reverse' will not be fully qualified unless we set the scheme/host/port here. # Authenticate and check request is has the relevant permissions
prefix = '%s://%s' % (request.is_secure() and 'https' or 'http', request.get_host()) self.check_permissions()
set_script_prefix(prefix)
try: # Get the appropriate handler method
# If using a form POST with '_method'/'_content'/'_content_type' overrides, then alter if self.method.lower() in self.http_method_names:
# self.method, self.content_type, self.RAW_CONTENT & self.CONTENT appropriately. handler = getattr(self, self.method.lower(), self.http_method_not_allowed)
self.perform_form_overloading() else:
handler = self.http_method_not_allowed
# Authenticate and check request is has the relevant permissions response_obj = handler(request, *args, **kwargs)
self.check_permissions()
# Get the appropriate handler method # Allow return value to be either Response, or an object, or None
if self.method.lower() in self.http_method_names: if isinstance(response_obj, Response):
handler = getattr(self, self.method.lower(), self.http_method_not_allowed) response = response_obj
else: elif response_obj is not None:
handler = self.http_method_not_allowed response = Response(status.HTTP_200_OK, response_obj)
else:
response = Response(status.HTTP_204_NO_CONTENT)
response_obj = handler(request, *args, **kwargs) # Pre-serialize filtering (eg filter complex objects into natively serializable types)
response.cleaned_content = self.cleanup_response(response.raw_content)
# Allow return value to be either Response, or an object, or None except ErrorResponse, exc:
if isinstance(response_obj, Response): response = exc.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) # Always add these headers.
response.cleaned_content = self.cleanup_response(response.raw_content) #
# 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'
except ErrorResponse, exc: return self.emit(response)
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()