diff options
| author | Tom Christie | 2011-05-02 19:49:12 +0100 |
|---|---|---|
| committer | Tom Christie | 2011-05-02 19:49:12 +0100 |
| commit | 8756664e064a18afc4713d921c318cd968f18433 (patch) | |
| tree | 8eb4499900552963f88972d0853e68d05159295f | |
| parent | b358fbdbe9cbd4ce644c4b2c7b9b4cec0811e14e (diff) | |
| download | django-rest-framework-8756664e064a18afc4713d921c318cd968f18433.tar.bz2 | |
emitters -> renderers
| -rw-r--r-- | djangorestframework/mixins.py | 90 | ||||
| -rw-r--r-- | djangorestframework/modelresource.py | 94 | ||||
| -rw-r--r-- | djangorestframework/renderers.py | 2 | ||||
| -rw-r--r-- | djangorestframework/resource.py | 10 | ||||
| -rw-r--r-- | examples/blogpost/models.py | 5 | ||||
| -rw-r--r-- | examples/blogpost/views.py | 7 | ||||
| -rw-r--r-- | examples/mixin/urls.py | 2 | ||||
| -rw-r--r-- | examples/pygments_api/views.py | 2 |
8 files changed, 111 insertions, 101 deletions
diff --git a/djangorestframework/mixins.py b/djangorestframework/mixins.py index ebeee31a..6bd83bfa 100644 --- a/djangorestframework/mixins.py +++ b/djangorestframework/mixins.py @@ -6,6 +6,7 @@ from djangorestframework import status from django.http import HttpResponse from django.http.multipartparser import LimitBytes # TODO: Use LimitedStream in compat + from StringIO import StringIO from decimal import Decimal import re @@ -233,7 +234,7 @@ class RequestMixin(object): @property def default_parser(self): - """Return the view's most preffered renderer. + """Return the view's most preferred renderer. (This has no behavioural effect, but is may be used by documenting renderers)""" return self.parsers[0] @@ -437,3 +438,90 @@ class AuthMixin(object): 'You may need to login or otherwise authenticate the request.'}) +########## Model Mixins ########## + +class ReadModelMixin(object): + """Behaviour to read a model instance on GET requests""" + 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 + + +class CreateModelMixin(object): + """Behaviour to create a model instance on POST requests""" + def post(self, request, *args, **kwargs): + # translated 'related_field' kwargs into 'related_field_id' + for related_name in [field.name for field in self.model._meta.fields if isinstance(field, RelatedField)]: + if kwargs.has_key(related_name): + kwargs[related_name + '_id'] = kwargs[related_name] + del kwargs[related_name] + + all_kw_args = dict(self.CONTENT.items() + kwargs.items()) + if args: + instance = self.model(pk=args[-1], **all_kw_args) + else: + instance = self.model(**all_kw_args) + instance.save() + headers = {} + if hasattr(instance, 'get_absolute_url'): + headers['Location'] = instance.get_absolute_url() + return Response(status.HTTP_201_CREATED, instance, headers) + + +class UpdateModelMixin(object): + """Behaviour to update a model instance on PUT requests""" + 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: + 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) + + for (key, val) in self.CONTENT.items(): + setattr(instance, key, val) + except self.model.DoesNotExist: + instance = self.model(**self.CONTENT) + instance.save() + + instance.save() + return instance + + +class DeleteModelMixin(object): + """Behaviour to delete a model instance on DELETE requests""" + def delete(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, None, {}) + + instance.delete() + return + + +class ListModelMixin(object): + """Behaviour to list a set of model instances on GET requests""" + queryset = None + + def get(self, request, *args, **kwargs): + queryset = self.queryset if self.queryset else self.model.objects.all() + return queryset.filter(**kwargs) + + diff --git a/djangorestframework/modelresource.py b/djangorestframework/modelresource.py index c61cc375..c286e586 100644 --- a/djangorestframework/modelresource.py +++ b/djangorestframework/modelresource.py @@ -341,94 +341,16 @@ 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 - - # translated related_field into related_field_id - for related_name in [field.name for field in self.model._meta.fields if isinstance(field, RelatedField)]: - if kwargs.has_key(related_name): - kwargs[related_name + '_id'] = kwargs[related_name] - del kwargs[related_name] - - all_kw_args = dict(self.CONTENT.items() + kwargs.items()) - if args: - instance = self.model(pk=args[-1], **all_kw_args) - else: - instance = self.model(**all_kw_args) - instance.save() - headers = {} - if hasattr(instance, 'get_absolute_url'): - headers['Location'] = instance.get_absolute_url() - return Response(status.HTTP_201_CREATED, instance, headers) - - 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: - 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) - - for (key, val) in self.CONTENT.items(): - setattr(instance, key, val) - except self.model.DoesNotExist: - instance = self.model(**self.CONTENT) - instance.save() - - instance.save() - return instance - - def delete(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, None, {}) - - instance.delete() - return -class InstanceModelResource(ModelResource): - http_method_names = ['get', 'put', 'delete', 'head', 'options', 'trace', 'patch'] # Bit of a hack, these - needs fixing. +class InstanceModelResource(ReadModelMixin, UpdateModelMixin, DeleteModelMixin, ModelResource): + """A view which provides default operations for read/update/delete against a model instance.""" + pass -class RootModelResource(ModelResource): +class ListOrCreateModelResource(CreateModelMixin, ListModelMixin, ModelResource): """A Resource which provides default operations for list and create.""" - queryset = None - - def get(self, request, *args, **kwargs): - queryset = self.queryset if self.queryset else self.model.objects.all() - return queryset.filter(**kwargs) - - http_method_names = ['get', 'post', 'head', 'options', 'trace', 'patch'] - -class QueryModelResource(ModelResource): - """Resource with default operations for list. - TODO: provide filter/order/num_results/paging, and a create operation to create queries.""" - allowed_methods = ('GET',) - queryset = None - - def get(self, request, *args, **kwargs): - queryset = self.queryset if self.queryset else self.model.objects.all() - return queryset.filer(**kwargs) + pass - http_method_names = ['get', 'head', 'options', 'trace', 'patch'] +class ListModelResource(ListModelMixin, ModelResource): + """Resource with default operations for list.""" + pass
\ No newline at end of file diff --git a/djangorestframework/renderers.py b/djangorestframework/renderers.py index e53dc061..2a07894e 100644 --- a/djangorestframework/renderers.py +++ b/djangorestframework/renderers.py @@ -43,7 +43,7 @@ class BaseRenderer(object): class TemplateRenderer(BaseRenderer): """Provided for convienience. - Emit the output by simply rendering it with the given template.""" + Render the output by simply rendering it with the given template.""" media_type = None template = None diff --git a/djangorestframework/resource.py b/djangorestframework/resource.py index 7879da7c..e06873ae 100644 --- a/djangorestframework/resource.py +++ b/djangorestframework/resource.py @@ -19,14 +19,12 @@ class Resource(RequestMixin, ResponseMixin, AuthMixin, View): """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'] - # List of renderers the resource can serialize the response with, ordered by preference. renderers = ( renderers.JSONRenderer, - renderers.DocumentingHTMLRenderer, - renderers.DocumentingXHTMLRenderer, - renderers.DocumentingPlainTextRenderer, - renderers.XMLRenderer ) + renderers.DocumentingHTMLRenderer, + renderers.DocumentingXHTMLRenderer, + renderers.DocumentingPlainTextRenderer, + renderers.XMLRenderer ) # List of parsers the resource can parse the request with. parsers = ( parsers.JSONParser, diff --git a/examples/blogpost/models.py b/examples/blogpost/models.py index 01a91e15..3489c596 100644 --- a/examples/blogpost/models.py +++ b/examples/blogpost/models.py @@ -12,6 +12,8 @@ RATING_CHOICES = ((0, 'Awful'), (3, 'Good'), (4, 'Excellent')) +MAX_POSTS = 10 + class BlogPost(models.Model): key = models.CharField(primary_key=True, max_length=64, default=uuid_str, editable=False) title = models.CharField(max_length=128) @@ -38,9 +40,10 @@ class BlogPost(models.Model): def save(self, *args, **kwargs): self.slug = slugify(self.title) super(self.__class__, self).save(*args, **kwargs) - for obj in self.__class__.objects.order_by('-pk')[10:]: + for obj in self.__class__.objects.order_by('-pk')[MAX_POSTS:]: obj.delete() + class Comment(models.Model): blogpost = models.ForeignKey(BlogPost, editable=False, related_name='comments') username = models.CharField(max_length=128) diff --git a/examples/blogpost/views.py b/examples/blogpost/views.py index e47f4a5b..c4b54f73 100644 --- a/examples/blogpost/views.py +++ b/examples/blogpost/views.py @@ -1,12 +1,11 @@ -from djangorestframework.modelresource import InstanceModelResource, RootModelResource +from djangorestframework.modelresource import InstanceModelResource, ListOrCreateModelResource from blogpost import models BLOG_POST_FIELDS = ('created', 'title', 'slug', 'content', 'absolute_url', 'comment_url', 'comments_url') COMMENT_FIELDS = ('username', 'comment', 'created', 'rating', 'absolute_url', 'blogpost_url') -MAX_POSTS = 10 -class BlogPosts(RootModelResource): +class BlogPosts(ListOrCreateModelResource): """A resource with which lists all existing blog posts and creates new blog posts.""" model = models.BlogPost fields = BLOG_POST_FIELDS @@ -16,7 +15,7 @@ class BlogPostInstance(InstanceModelResource): model = models.BlogPost fields = BLOG_POST_FIELDS -class Comments(RootModelResource): +class Comments(ListOrCreateModelResource): """A resource which lists all existing comments for a given blog post, and creates new blog comments for a given blog post.""" model = models.Comment fields = COMMENT_FIELDS diff --git a/examples/mixin/urls.py b/examples/mixin/urls.py index f4300f41..1d25f6c7 100644 --- a/examples/mixin/urls.py +++ b/examples/mixin/urls.py @@ -15,7 +15,7 @@ class ExampleView(ResponseMixin, View): def get(self, request): response = Response(200, {'description': 'Some example content', 'url': reverse('mixin-view')}) - return self.emit(response) + return self.render(response) urlpatterns = patterns('', diff --git a/examples/pygments_api/views.py b/examples/pygments_api/views.py index 278e8250..253b0907 100644 --- a/examples/pygments_api/views.py +++ b/examples/pygments_api/views.py @@ -68,7 +68,7 @@ class PygmentsRoot(Resource): class PygmentsInstance(Resource): """Simply return the stored highlighted HTML file with the correct mime type. - This Resource only emits HTML and uses a standard HTML renderer rather than the renderers.DocumentingHTMLRenderer class.""" + This Resource only renders HTML and uses a standard HTML renderer rather than the renderers.DocumentingHTMLRenderer class.""" renderers = (HTMLRenderer,) def get(self, request, unique_id): |
