diff --git a/djangorestframework/mixins.py b/djangorestframework/mixins.py index 4d1731787..7bed131bc 100644 --- a/djangorestframework/mixins.py +++ b/djangorestframework/mixins.py @@ -11,7 +11,7 @@ from django.http.multipartparser import LimitBytes from djangorestframework import status from djangorestframework.parsers import FormParser, MultiPartParser -from djangorestframework.resources import Resource +from djangorestframework.resources import Resource, FormResource, ModelResource from djangorestframework.response import Response, ErrorResponse from djangorestframework.utils import as_tuple, MSIE_USER_AGENT_REGEX from djangorestframework.utils.mediatypes import is_form_media_type, order_by_precedence @@ -395,7 +395,7 @@ class ResourceMixin(object): It provides validation on the content of incoming requests, and filters the object representation into a serializable object for the response. """ - resource = Resource + resource = None @property def CONTENT(self): @@ -406,24 +406,31 @@ class ResourceMixin(object): self._content = self.validate_request(self.DATA, self.FILES) return self._content + @property + def _resource(self): + if self.resource: + return self.resource(self) + elif hasattr(self, 'model'): + return ModelResource(self) + elif hasattr(self, 'form'): + return FormResource(self) + return Resource(self) + def validate_request(self, data, files): """ Given the request *data* return the cleaned, validated content. Typically raises an :class:`response.ErrorResponse` with status code 400 (Bad Request) on failure. """ - resource = self.resource(self) - return resource.validate_request(data, files) + return self._resource.validate_request(data, files) def filter_response(self, obj): """ Given the response content, filter it into a serializable object. """ - resource = self.resource(self) - return resource.filter_response(obj) + return self._resource.filter_response(obj) def get_bound_form(self, content=None): - resource = self.resource(self) - return resource.get_bound_form(content) + return self._resource.get_bound_form(content) diff --git a/djangorestframework/resources.py b/djangorestframework/resources.py index 27d25ba9d..de8e1351c 100644 --- a/djangorestframework/resources.py +++ b/djangorestframework/resources.py @@ -165,11 +165,22 @@ class FormResource(Resource): On calling :meth:`validate_request` this validator may set a :attr:`bound_form_instance` attribute on the view, which may be used by some renderers. """ - form = None + """ The :class:`Form` class that should be used for request validation. + This can be overridden by a :attr:`form` attribute on the :class:`.View`. """ - + form = None + + def __init__(self, view): + """ + Allow a :attr:`form` attributes set on the :class:`View` to override + the :attr:`form` attribute set on the :class:`Resource`. + """ + super(FormResource, self).__init__(view) + + if getattr(view, 'form', None): + self.form = view.form def validate_request(self, data, files): @@ -314,11 +325,15 @@ class ModelResource(FormResource): """ The form class that should be used for request validation. If set to :const:`None` then the default model form validation will be used. + + This can be overridden by a :attr:`form` attribute on the :class:`.View`. """ form = None """ The model class which this resource maps to. + + This can be overridden by a :attr:`model` attribute on the :class:`.View`. """ model = None @@ -346,6 +361,17 @@ class ModelResource(FormResource): include = ('url',) + def __init__(self, view): + """ + Allow :attr:`form` and :attr:`model` attributes set on the + :class:`View` to override the :attr:`form` and :attr:`model` + attributes set on the :class:`Resource`. + """ + super(ModelResource, self).__init__(view) + + if getattr(view, 'model', None): + self.model = view.model + def validate_request(self, data, files): """ Given some content as input return some cleaned, validated content. diff --git a/djangorestframework/views.py b/djangorestframework/views.py index cdb2ba33d..1315229af 100644 --- a/djangorestframework/views.py +++ b/djangorestframework/views.py @@ -31,27 +31,38 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView): Performs request deserialization, response serialization, authentication and input validation. """ - # Use the base resource by default - resource = resources.Resource + """ + The resource to use when validating requests and filtering responses, + or `None` to use default behaviour. + """ + resource = None + """ + List of renderers the resource can serialize the response with, ordered by preference. + """ renderers = ( renderers.JSONRenderer, renderers.DocumentingHTMLRenderer, renderers.DocumentingXHTMLRenderer, renderers.DocumentingPlainTextRenderer, renderers.XMLRenderer ) - """ List of renderers the resource can serialize the response with, ordered by preference.""" + """ + List of parsers the resource can parse the request with. + """ parsers = ( parsers.JSONParser, parsers.FormParser, parsers.MultiPartParser ) - """ List of parsers the resource can parse the request with.""" + """ + List of all authenticating methods to attempt. + """ authentication = ( authentication.UserLoggedInAuthenticaton, authentication.BasicAuthenticaton ) - """ List of all authenticating methods to attempt.""" + """ + List of all permissions that must be checked. + """ permissions = ( permissions.FullAnonAccess, ) - """ List of all permissions that must be checked.""" # Allow name and description for the Resource to be set explicitly, # overiding the default classname/docstring behaviour.