mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-25 23:50:01 +03:00
added tests, and fixed bugs
changed whole empty stuff - was just wrong or useless
This commit is contained in:
parent
6f56b6279f
commit
2771b596d1
|
@ -344,12 +344,6 @@ except ImportError:
|
|||
return datetime.datetime(**kw)
|
||||
|
||||
|
||||
# empty does not exist in 1.3x
|
||||
if django.VERSION >= (1, 4):
|
||||
from django.utils.functional import empty
|
||||
else:
|
||||
empty = object()
|
||||
|
||||
# Markdown is optional
|
||||
try:
|
||||
import markdown
|
||||
|
|
|
@ -20,6 +20,12 @@ from rest_framework.compat import parse_date, parse_datetime
|
|||
from rest_framework.compat import timezone
|
||||
from urlparse import urlparse
|
||||
|
||||
class Empty(object):
|
||||
"""
|
||||
Placeholder for unset attributes.
|
||||
Cannot use `None`, as that may be a valid value.
|
||||
"""
|
||||
pass
|
||||
|
||||
def is_simple_callable(obj):
|
||||
"""
|
||||
|
@ -530,7 +536,7 @@ class HyperlinkedRelatedField(RelatedField):
|
|||
except:
|
||||
raise ValueError("Hyperlinked field requires 'view_name' kwarg")
|
||||
|
||||
self.view_namespace = kwargs.pop('view_namespace', None)
|
||||
self.view_namespace = kwargs.pop('view_namespace', Empty)
|
||||
|
||||
self.slug_field = kwargs.pop('slug_field', self.slug_field)
|
||||
default_slug_kwarg = self.slug_url_kwarg or self.slug_field
|
||||
|
@ -540,6 +546,15 @@ class HyperlinkedRelatedField(RelatedField):
|
|||
self.format = kwargs.pop('format', None)
|
||||
super(HyperlinkedRelatedField, self).__init__(*args, **kwargs)
|
||||
|
||||
def initialize(self, parent, field_name):
|
||||
super(HyperlinkedRelatedField, self).initialize(parent, field_name)
|
||||
|
||||
if self.view_namespace is Empty:
|
||||
self.view_namespace = getattr(self.parent.opts, 'view_namespace', None)
|
||||
|
||||
if self.view_namespace:
|
||||
self.view_name = '%(namespace)s:%(name)s' % {'namespace': self.view_namespace, 'name': self.view_name}
|
||||
|
||||
def get_slug_field(self):
|
||||
"""
|
||||
Get the name of a slug field to be used to look up by slug.
|
||||
|
@ -547,10 +562,7 @@ class HyperlinkedRelatedField(RelatedField):
|
|||
return self.slug_field
|
||||
|
||||
def to_native(self, obj):
|
||||
view_namespace = self.view_namespace
|
||||
view_name = self.view_name
|
||||
if view_namespace:
|
||||
view_name = '%(namespace)s:%(name)s' % {'namespace': view_namespace, 'name': view_name}
|
||||
|
||||
request = self.context.get('request', None)
|
||||
format = self.format or self.context.get('format', None)
|
||||
|
@ -645,7 +657,7 @@ class HyperlinkedIdentityField(Field):
|
|||
except:
|
||||
raise ValueError("Hyperlinked Identity field requires 'view_name' kwarg")
|
||||
|
||||
self.view_namespace = kwargs.pop('view_namespace', None)
|
||||
self.view_namespace = kwargs.pop('view_namespace', Empty)
|
||||
|
||||
self.format = kwargs.pop('format', None)
|
||||
|
||||
|
@ -654,15 +666,22 @@ class HyperlinkedIdentityField(Field):
|
|||
self.pk_url_kwarg = kwargs.pop('pk_url_kwarg', self.pk_url_kwarg)
|
||||
self.slug_url_kwarg = kwargs.pop('slug_url_kwarg', default_slug_kwarg)
|
||||
|
||||
super(HyperlinkedIdentityField, self).__init__(*args, **kwargs)
|
||||
super(HyperlinkedIdentityField, self).__init__(*args, **kwargs)
|
||||
|
||||
def initialize(self, parent, field_name):
|
||||
super(HyperlinkedIdentityField, self).initialize(parent, field_name)
|
||||
|
||||
if self.view_namespace is Empty:
|
||||
self.view_namespace = getattr(self.parent.opts, 'view_namespace', None)
|
||||
|
||||
if self.view_namespace:
|
||||
self.view_name = '%(namespace)s:%(name)s' % {'namespace': self.view_namespace, 'name': self.view_name}
|
||||
|
||||
|
||||
def field_to_native(self, obj, field_name):
|
||||
request = self.context.get('request', None)
|
||||
format = self.format or self.context.get('format', None)
|
||||
view_namespace = self.view_namespace
|
||||
view_name = self.view_name
|
||||
if view_namespace:
|
||||
view_name = '%(namespace)s:%(name)s' % {'namespace': view_namespace, 'name': view_name}
|
||||
|
||||
kwargs = {self.pk_url_kwarg: obj.pk}
|
||||
try:
|
||||
|
|
|
@ -6,7 +6,7 @@ from django.db import models
|
|||
from django.forms import widgets
|
||||
from django.utils.datastructures import SortedDict
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from rest_framework.compat import get_concrete_model, empty
|
||||
from rest_framework.compat import get_concrete_model
|
||||
|
||||
# Note: We do the following so that users of the framework can use this style:
|
||||
#
|
||||
|
@ -69,7 +69,7 @@ def _get_declared_fields(bases, attrs):
|
|||
return SortedDict(fields)
|
||||
|
||||
def _get_options_instance(bases, attrs):
|
||||
options_class = Meta = empty
|
||||
options_class = Meta = None
|
||||
if '_options_class' in attrs:
|
||||
options_class = attrs['_options_class']
|
||||
else:
|
||||
|
@ -77,7 +77,7 @@ def _get_options_instance(bases, attrs):
|
|||
if hasattr(base, '_options_class'):
|
||||
options_class = getattr(base, '_options_class')
|
||||
break
|
||||
if options_class is empty:
|
||||
if options_class is None:
|
||||
raise ImproperlyConfigured, 'A Serializer requires an "_options_class" attribute'
|
||||
|
||||
if 'Meta' in attrs:
|
||||
|
@ -87,7 +87,7 @@ def _get_options_instance(bases, attrs):
|
|||
if hasattr(base, 'Meta'):
|
||||
Meta = getattr(base, 'Meta')
|
||||
break
|
||||
if Meta is empty:
|
||||
if Meta is None:
|
||||
raise ImproperlyConfigured, 'A Serializer requires an "Meta" attribute'
|
||||
|
||||
return options_class(Meta)
|
||||
|
|
|
@ -16,6 +16,16 @@ class BlogPostCommentSerializer(serializers.ModelSerializer):
|
|||
model = BlogPostComment
|
||||
fields = ('text', 'blog_post_url', 'url')
|
||||
|
||||
class NamespacedBlogPostCommentSerializer(serializers.HyperlinkedModelSerializer):
|
||||
url = serializers.HyperlinkedIdentityField(view_name='blogpostcomment-detail')
|
||||
text = serializers.CharField()
|
||||
blog_post_url = serializers.HyperlinkedRelatedField(source='blog_post', view_name='blogpost-detail', view_namespace = None)
|
||||
|
||||
class Meta:
|
||||
model = BlogPostComment
|
||||
view_namespace = 'namespacetests'
|
||||
fields = ('text', 'blog_post_url', 'url')
|
||||
|
||||
|
||||
class PhotoSerializer(serializers.Serializer):
|
||||
description = serializers.CharField()
|
||||
|
@ -65,6 +75,14 @@ class BlogPostCommentDetail(generics.RetrieveAPIView):
|
|||
model = BlogPostComment
|
||||
serializer_class = BlogPostCommentSerializer
|
||||
|
||||
class NamespacedBlogPostCommentListCreate(generics.ListCreateAPIView):
|
||||
model = BlogPostComment
|
||||
serializer_class = NamespacedBlogPostCommentSerializer
|
||||
|
||||
class NamespacedBlogPostCommentDetail(generics.RetrieveAPIView):
|
||||
model = BlogPostComment
|
||||
serializer_class = NamespacedBlogPostCommentSerializer
|
||||
|
||||
class BlogPostDetail(generics.RetrieveAPIView):
|
||||
model = BlogPost
|
||||
|
||||
|
@ -86,6 +104,8 @@ class OptionalRelationDetail(generics.RetrieveAPIView):
|
|||
anchor_urls = patterns('',
|
||||
url(r'^(?P<pk>\d+)/$', AnchorDetail.as_view(), name='anchor-detail'),
|
||||
url(r'^manytomany/(?P<pk>\d+)/$', NamespacedManyToManyDetail.as_view(), name='manytomanymodel-detail'),
|
||||
url(r'^comments/$', NamespacedBlogPostCommentListCreate.as_view(), name='blogpostcomment-list'),
|
||||
url(r'^comments/(?P<pk>\d+)/$', NamespacedBlogPostCommentDetail.as_view(), name='blogpostcomment-detail'),
|
||||
)
|
||||
|
||||
urlpatterns = patterns('',
|
||||
|
@ -216,6 +236,7 @@ class TestCreateWithForeignKeys(TestCase):
|
|||
"""
|
||||
self.post = BlogPost.objects.create(title="Test post")
|
||||
self.create_view = BlogPostCommentListCreate.as_view()
|
||||
self.create_namespaced_view = NamespacedBlogPostCommentListCreate.as_view()
|
||||
|
||||
def test_create_comment(self):
|
||||
|
||||
|
@ -231,6 +252,26 @@ class TestCreateWithForeignKeys(TestCase):
|
|||
self.assertEqual(self.post.blogpostcomment_set.count(), 1)
|
||||
self.assertEqual(self.post.blogpostcomment_set.all()[0].text, 'A test comment')
|
||||
|
||||
def test_create_namespaced_comment(self):
|
||||
|
||||
data = {
|
||||
'text': 'A test comment',
|
||||
'blog_post_url': 'http://testserver/posts/1/'
|
||||
}
|
||||
|
||||
response_data = {
|
||||
'url': 'http://testserver/other/namespace/comments/1/',
|
||||
'text': 'A test comment',
|
||||
'blog_post_url': 'http://testserver/posts/1/'
|
||||
}
|
||||
|
||||
request = factory.post('/other/namespace/comments/', data=data)
|
||||
response = self.create_namespaced_view(request).render()
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(response['Location'], 'http://testserver/other/namespace/comments/1/', msg='Not specified Namespace should be inherited from parents Options')
|
||||
self.assertEqual(self.post.blogpostcomment_set.count(), 1)
|
||||
self.assertEquals(response.data, response_data)
|
||||
|
||||
|
||||
class TestCreateWithForeignKeysAndCustomSlug(TestCase):
|
||||
urls = 'rest_framework.tests.hyperlinkedserializers'
|
||||
|
|
Loading…
Reference in New Issue
Block a user