mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-03-19 17:34:13 +03:00
emitters -> renderers
This commit is contained in:
parent
b358fbdbe9
commit
8756664e06
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
pass
|
||||
|
||||
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)
|
||||
|
||||
http_method_names = ['get', 'head', 'options', 'trace', 'patch']
|
||||
class ListModelResource(ListModelMixin, ModelResource):
|
||||
"""Resource with default operations for list."""
|
||||
pass
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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('',
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue
Block a user