made changes requested by Tom. In resources : removed decorators, and 'request' parameter from the crud methods

This commit is contained in:
Sébastien Piquemal 2012-01-09 20:00:18 +02:00
parent d1c217523b
commit 3a52c213f9
4 changed files with 67 additions and 51 deletions

View File

@ -471,12 +471,21 @@ class ResourceMixin(object):
""" """
return self.deserialize(self.request.GET) return self.deserialize(self.request.GET)
@property def get_resource_class(self):
def resource(self): if self.resource_class:
if not hasattr(self, '_resource'): return self.resource_class
self._resource = self.resource_class(view=self) elif getattr(self, 'model', None):
return self._resource return ModelResource
elif getattr(self, 'form', None):
return FormResource
elif hasattr(self, 'request') and getattr(self, '%s_form' % self.method.lower(), None):
return FormResource
else:
return Resource
def get_resource(self):
resource_class = self.get_resource_class()
return resource_class(view=self)
@ -496,6 +505,7 @@ class InstanceMixin(object):
associated with this view. associated with this view.
""" """
view = super(InstanceMixin, cls).as_view(**initkwargs) view = super(InstanceMixin, cls).as_view(**initkwargs)
# TODO: FIX !!! Very bad now, since this is attached on the class (thread-safety)
resource_class = getattr(cls(**initkwargs), 'resource_class', None) resource_class = getattr(cls(**initkwargs), 'resource_class', None)
if resource_class: if resource_class:
# We do a little dance when we store the view callable... # We do a little dance when we store the view callable...
@ -512,51 +522,55 @@ class InstanceMixin(object):
class GetResourceMixin(object): class GetResourceMixin(object):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
resource = self.get_resource()
try: try:
self.resource.retrieve(request, *args, **kwargs) resource.retrieve(*args, **kwargs)
except self.resource.DoesNotExist: except resource.DoesNotExist:
raise ErrorResponse(status.HTTP_404_NOT_FOUND) raise ErrorResponse(status.HTTP_404_NOT_FOUND)
return self.resource.instance return resource.instance
class PostResourceMixin(object): class PostResourceMixin(object):
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
self.resource.create(request, *args, **kwargs) resource = self.get_resource()
self.resource.update(self.CONTENT, request, *args, **kwargs) resource.create(*args, **kwargs)
headers = {'Location': self.resource.get_url()} resource.update(self.CONTENT, *args, **kwargs)
return Response(status.HTTP_201_CREATED, self.resource.instance, headers) headers = {'Location': resource.get_url()}
return Response(status.HTTP_201_CREATED, resource.instance, headers)
class PutResourceMixin(object): class PutResourceMixin(object):
def put(self, request, *args, **kwargs): def put(self, request, *args, **kwargs):
headers = {} resource = self.get_resource()
try: try:
self.resource.retrieve(request, *args, **kwargs) resource.retrieve(*args, **kwargs)
status_code = status.HTTP_204_NO_CONTENT status_code = status.HTTP_204_NO_CONTENT
except self.resource.DoesNotExist: except resource.DoesNotExist:
self.resource.create(request, *args, **kwargs) resource.create(*args, **kwargs)
status_code = status.HTTP_201_CREATED status_code = status.HTTP_201_CREATED
self.resource.update(self.CONTENT, request, *args, **kwargs) resource.update(self.CONTENT, *args, **kwargs)
return Response(status_code, self.resource.instance, {}) return Response(status_code, resource.instance, {})
class DeleteResourceMixin(object): class DeleteResourceMixin(object):
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
resource = self.get_resource()
try: try:
self.resource.retrieve(request, *args, **kwargs) resource.retrieve(*args, **kwargs)
except self.resource.DoesNotExist: except resource.DoesNotExist:
raise ErrorResponse(status.HTTP_404_NOT_FOUND) raise ErrorResponse(status.HTTP_404_NOT_FOUND)
self.resource.delete(request, *args, **kwargs) resource.delete(*args, **kwargs)
return return
class ListResourceMixin(object): class ListResourceMixin(object):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
return self.resource.list(request, *args, **kwargs) resource = self.get_resource()
return resource.list(*args, **kwargs)
########## Pagination Mixins ########## ########## Pagination Mixins ##########

View File

@ -216,4 +216,4 @@ class PerResourceThrottling(BaseThrottle):
""" """
def get_cache_key(self): def get_cache_key(self):
return 'throttle_resource_%s' % self.view.resource.__class__.__name__ return 'throttle_resource_%s' % self.view.get_resource_class().__name__

View File

@ -6,14 +6,6 @@ from djangorestframework.response import ErrorResponse
from djangorestframework.serializer import Serializer, _SkipField from djangorestframework.serializer import Serializer, _SkipField
def bound_resource_required(meth):
def _decorated(self, *args, **kwargs):
if not self.is_bound():
raise Exception("resource needs to be bound") #TODO: what exception?
return meth(self, *args, **kwargs)
return _decorated
class BaseResource(Serializer): class BaseResource(Serializer):
""" """
Base class for all Resource classes, which simply defines the interface Base class for all Resource classes, which simply defines the interface
@ -26,7 +18,8 @@ class BaseResource(Serializer):
# TODO: Inheritance, like for models # TODO: Inheritance, like for models
class DoesNotExist(Exception): pass class DoesNotExist(Exception): pass
def __init__(self, instance=None, view=None, depth=None, stack=[], **kwargs): # !!! `view` should be first kwarg to avoid backward incompatibilities. (lol)
def __init__(self, view=None, instance=None, depth=None, stack=[], **kwargs):
super(BaseResource, self).__init__(depth, stack, **kwargs) super(BaseResource, self).__init__(depth, stack, **kwargs)
self.view = view self.view = view
self.instance = instance self.instance = instance
@ -39,21 +32,18 @@ class BaseResource(Serializer):
""" """
return data return data
def retrieve(self, request, *args, **kwargs): def retrieve(self, *args, **kwargs):
raise NotImplementedError() raise NotImplementedError()
def create(self, request, *args, **kwargs): def create(self, *args, **kwargs):
raise NotImplementedError() raise NotImplementedError()
@bound_resource_required def update(self, data, *args, **kwargs):
def update(self, data, request, *args, **kwargs):
raise NotImplementedError() raise NotImplementedError()
@bound_resource_required def delete(self, *args, **kwargs):
def delete(self, request, *args, **kwargs):
raise NotImplementedError() raise NotImplementedError()
@bound_resource_required
def get_url(self): def get_url(self):
raise NotImplementedError() raise NotImplementedError()
@ -148,7 +138,8 @@ class FormResource(Resource):
if bound_form is None: if bound_form is None:
return data return data
self.view.bound_form_instance = bound_form if self.view is not None:
self.view.bound_form_instance = bound_form
data = data and data or {} data = data and data or {}
files = files and files or {} files = files and files or {}
@ -314,17 +305,17 @@ class ModelResource(FormResource):
is not set. is not set.
""" """
def __init__(self, instance=None, view=None, depth=None, stack=[], **kwargs): def __init__(self, view=None, instance=None, depth=None, stack=[], **kwargs):
""" """
Allow :attr:`form` and :attr:`model` attributes set on the Allow :attr:`form` and :attr:`model` attributes set on the
:class:`View` to override the :attr:`form` and :attr:`model` :class:`View` to override the :attr:`form` and :attr:`model`
attributes set on the :class:`Resource`. attributes set on the :class:`Resource`.
""" """
super(ModelResource, self).__init__(instance=instance, view=view, depth=depth, stack=stack, **kwargs) super(ModelResource, self).__init__(view=None, instance=instance, depth=depth, stack=stack, **kwargs)
self.model = getattr(view, 'model', None) or self.model self.model = getattr(view, 'model', None) or self.model
def retrieve(self, request, *args, **kwargs): def retrieve(self, *args, **kwargs):
""" """
Return a model instance or None. Return a model instance or None.
""" """
@ -339,7 +330,7 @@ class ModelResource(FormResource):
self.instance = instance self.instance = instance
return self.instance return self.instance
def create(self, request, *args, **kwargs): def create(self, *args, **kwargs):
model = self.get_model() model = self.get_model()
kwargs = self._clean_url_kwargs(kwargs) kwargs = self._clean_url_kwargs(kwargs)
@ -347,8 +338,12 @@ class ModelResource(FormResource):
self.instance.save() self.instance.save()
return self.instance return self.instance
@bound_resource_required def update(self, data, *args, **kwargs):
def update(self, data, request, *args, **kwargs): # The resource needs to be bound to an
# instance, or updating is not possible
if not self.is_bound():
raise Exception("resource needs to be bound") #TODO: what exception?
model = self.get_model() model = self.get_model()
kwargs = self._clean_url_kwargs(kwargs) kwargs = self._clean_url_kwargs(kwargs)
data = dict(data, **kwargs) data = dict(data, **kwargs)
@ -382,12 +377,16 @@ class ModelResource(FormResource):
self.instance.save() self.instance.save()
return self.instance return self.instance
@bound_resource_required def delete(self, *args, **kwargs):
def delete(self, request, *args, **kwargs): # The resource needs to be bound to an
# instance, or deleting is not possible
if not self.is_bound():
raise Exception("resource needs to be bound") #TODO: what exception?
self.instance.delete() self.instance.delete()
return self.instance return self.instance
def list(self, request, *args, **kwargs): def list(self, *args, **kwargs):
# TODO: QuerysetResource instead !? # TODO: QuerysetResource instead !?
kwargs = self._clean_url_kwargs(kwargs) kwargs = self._clean_url_kwargs(kwargs)
queryset = self.get_queryset() queryset = self.get_queryset()
@ -397,7 +396,6 @@ class ModelResource(FormResource):
queryset = queryset.order_by(ordering) queryset = queryset.order_by(ordering)
return queryset.filter(**kwargs) return queryset.filter(**kwargs)
@bound_resource_required
def get_url(self): def get_url(self):
""" """
Attempts to reverse resolve the url of the given model *instance* for Attempts to reverse resolve the url of the given model *instance* for
@ -409,6 +407,10 @@ class ModelResource(FormResource):
This method can be overridden if you need to set the resource url This method can be overridden if you need to set the resource url
reversing explicitly. reversing explicitly.
""" """
# The resource needs to be bound to an
# instance, or getting url is not possible
if not self.is_bound():
raise Exception("resource needs to be bound") #TODO: what exception?
if not hasattr(self, 'view_callable'): if not hasattr(self, 'view_callable'):
raise _SkipField raise _SkipField

View File

@ -157,7 +157,7 @@ class RendererIntegrationTests(TestCase):
_flat_repr = '{"foo": ["bar", "baz"]}' _flat_repr = '{"foo": ["bar", "baz"]}'
_indented_repr = '{\n "foo": [\n "bar", \n "baz"\n ]\n}' _indented_repr = '{\n "foo": [\n "bar",\n "baz"\n ]\n}'
class JSONRendererTests(TestCase): class JSONRendererTests(TestCase):