aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework/tests/serializer.py
diff options
context:
space:
mode:
authorTom Christie2012-10-30 14:32:31 +0000
committerTom Christie2012-10-30 14:32:31 +0000
commit9b30dab4f772f67a626e176dc4fae0a3ef9c2c81 (patch)
treeca138abf4792f58ffa28684f784f201ee1eef6d7 /rest_framework/tests/serializer.py
parent7e5b1501b5cede61a9391fb1a751d2ebcdb37031 (diff)
parent4e7805cb24d73e7f706318b5e5a27e3f9ba39d14 (diff)
downloaddjango-rest-framework-9b30dab4f772f67a626e176dc4fae0a3ef9c2c81.tar.bz2
Merge branch 'restframework2' into rest-framework-2-merge2.0.0
Conflicts: .gitignore .travis.yml AUTHORS README.rst djangorestframework/mixins.py djangorestframework/renderers.py djangorestframework/resources.py djangorestframework/serializer.py djangorestframework/templates/djangorestframework/base.html djangorestframework/templates/djangorestframework/login.html djangorestframework/templatetags/add_query_param.py djangorestframework/tests/accept.py djangorestframework/tests/authentication.py djangorestframework/tests/content.py djangorestframework/tests/reverse.py djangorestframework/tests/serializer.py djangorestframework/views.py docs/examples.rst docs/examples/blogpost.rst docs/examples/modelviews.rst docs/examples/objectstore.rst docs/examples/permissions.rst docs/examples/pygments.rst docs/examples/views.rst docs/howto/alternativeframeworks.rst docs/howto/mixin.rst docs/howto/reverse.rst docs/howto/usingurllib2.rst docs/index.rst docs/topics/release-notes.md examples/sandbox/views.py rest_framework/__init__.py rest_framework/compat.py rest_framework/utils/breadcrumbs.py setup.py
Diffstat (limited to 'rest_framework/tests/serializer.py')
-rw-r--r--rest_framework/tests/serializer.py500
1 files changed, 500 insertions, 0 deletions
diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py
new file mode 100644
index 00000000..d4b43862
--- /dev/null
+++ b/rest_framework/tests/serializer.py
@@ -0,0 +1,500 @@
+import datetime
+from django.test import TestCase
+from rest_framework import serializers
+from rest_framework.tests.models import *
+
+
+class SubComment(object):
+ def __init__(self, sub_comment):
+ self.sub_comment = sub_comment
+
+
+class Comment(object):
+ def __init__(self, email, content, created):
+ self.email = email
+ self.content = content
+ self.created = created or datetime.datetime.now()
+
+ def __eq__(self, other):
+ return all([getattr(self, attr) == getattr(other, attr)
+ for attr in ('email', 'content', 'created')])
+
+ def get_sub_comment(self):
+ sub_comment = SubComment('And Merry Christmas!')
+ return sub_comment
+
+
+class CommentSerializer(serializers.Serializer):
+ email = serializers.EmailField()
+ content = serializers.CharField(max_length=1000)
+ created = serializers.DateTimeField()
+ sub_comment = serializers.Field(source='get_sub_comment.sub_comment')
+
+ def restore_object(self, data, instance=None):
+ if instance is None:
+ return Comment(**data)
+ for key, val in data.items():
+ setattr(instance, key, val)
+ return instance
+
+
+class ActionItemSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = ActionItem
+
+
+class PersonSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Person
+
+
+class BasicTests(TestCase):
+ def setUp(self):
+ self.comment = Comment(
+ 'tom@example.com',
+ 'Happy new year!',
+ datetime.datetime(2012, 1, 1)
+ )
+ self.data = {
+ 'email': 'tom@example.com',
+ 'content': 'Happy new year!',
+ 'created': datetime.datetime(2012, 1, 1),
+ 'sub_comment': 'This wont change'
+ }
+ self.expected = {
+ 'email': 'tom@example.com',
+ 'content': 'Happy new year!',
+ 'created': datetime.datetime(2012, 1, 1),
+ 'sub_comment': 'And Merry Christmas!'
+ }
+
+ def test_empty(self):
+ serializer = CommentSerializer()
+ expected = {
+ 'email': '',
+ 'content': '',
+ 'created': None,
+ 'sub_comment': ''
+ }
+ self.assertEquals(serializer.data, expected)
+
+ def test_retrieve(self):
+ serializer = CommentSerializer(instance=self.comment)
+ self.assertEquals(serializer.data, self.expected)
+
+ def test_create(self):
+ serializer = CommentSerializer(self.data)
+ expected = self.comment
+ self.assertEquals(serializer.is_valid(), True)
+ self.assertEquals(serializer.object, expected)
+ self.assertFalse(serializer.object is expected)
+ self.assertEquals(serializer.data['sub_comment'], 'And Merry Christmas!')
+
+ def test_update(self):
+ serializer = CommentSerializer(self.data, instance=self.comment)
+ expected = self.comment
+ self.assertEquals(serializer.is_valid(), True)
+ self.assertEquals(serializer.object, expected)
+ self.assertTrue(serializer.object is expected)
+ self.assertEquals(serializer.data['sub_comment'], 'And Merry Christmas!')
+
+
+class ValidationTests(TestCase):
+ def setUp(self):
+ self.comment = Comment(
+ 'tom@example.com',
+ 'Happy new year!',
+ datetime.datetime(2012, 1, 1)
+ )
+ self.data = {
+ 'email': 'tom@example.com',
+ 'content': 'x' * 1001,
+ 'created': datetime.datetime(2012, 1, 1)
+ }
+ self.actionitem = ActionItem('Some to do item',
+ )
+
+ def test_create(self):
+ serializer = CommentSerializer(self.data)
+ self.assertEquals(serializer.is_valid(), False)
+ self.assertEquals(serializer.errors, {'content': [u'Ensure this value has at most 1000 characters (it has 1001).']})
+
+ def test_update(self):
+ serializer = CommentSerializer(self.data, instance=self.comment)
+ self.assertEquals(serializer.is_valid(), False)
+ self.assertEquals(serializer.errors, {'content': [u'Ensure this value has at most 1000 characters (it has 1001).']})
+
+ def test_update_missing_field(self):
+ data = {
+ 'content': 'xxx',
+ 'created': datetime.datetime(2012, 1, 1)
+ }
+ serializer = CommentSerializer(data, instance=self.comment)
+ self.assertEquals(serializer.is_valid(), False)
+ self.assertEquals(serializer.errors, {'email': [u'This field is required.']})
+
+ def test_missing_bool_with_default(self):
+ """Make sure that a boolean value with a 'False' value is not
+ mistaken for not having a default."""
+ data = {
+ 'title': 'Some action item',
+ #No 'done' value.
+ }
+ serializer = ActionItemSerializer(data, instance=self.actionitem)
+ self.assertEquals(serializer.is_valid(), True)
+ self.assertEquals(serializer.errors, {})
+
+ def test_field_validation(self):
+
+ class CommentSerializerWithFieldValidator(CommentSerializer):
+
+ def validate_content(self, attrs, source):
+ value = attrs[source]
+ if "test" not in value:
+ raise serializers.ValidationError("Test not in value")
+ return attrs
+
+ data = {
+ 'email': 'tom@example.com',
+ 'content': 'A test comment',
+ 'created': datetime.datetime(2012, 1, 1)
+ }
+
+ serializer = CommentSerializerWithFieldValidator(data)
+ self.assertTrue(serializer.is_valid())
+
+ data['content'] = 'This should not validate'
+
+ serializer = CommentSerializerWithFieldValidator(data)
+ self.assertFalse(serializer.is_valid())
+ self.assertEquals(serializer.errors, {'content': [u'Test not in value']})
+
+ def test_cross_field_validation(self):
+
+ class CommentSerializerWithCrossFieldValidator(CommentSerializer):
+
+ def validate(self, attrs):
+ if attrs["email"] not in attrs["content"]:
+ raise serializers.ValidationError("Email address not in content")
+ return attrs
+
+ data = {
+ 'email': 'tom@example.com',
+ 'content': 'A comment from tom@example.com',
+ 'created': datetime.datetime(2012, 1, 1)
+ }
+
+ serializer = CommentSerializerWithCrossFieldValidator(data)
+ self.assertTrue(serializer.is_valid())
+
+ data['content'] = 'A comment from foo@bar.com'
+
+ serializer = CommentSerializerWithCrossFieldValidator(data)
+ self.assertFalse(serializer.is_valid())
+ self.assertEquals(serializer.errors, {'non_field_errors': [u'Email address not in content']})
+
+ def test_null_is_true_fields(self):
+ """
+ Omitting a value for null-field should validate.
+ """
+ serializer = PersonSerializer({'name': 'marko'})
+ self.assertEquals(serializer.is_valid(), True)
+ self.assertEquals(serializer.errors, {})
+
+
+class MetadataTests(TestCase):
+ def test_empty(self):
+ serializer = CommentSerializer()
+ expected = {
+ 'email': serializers.CharField,
+ 'content': serializers.CharField,
+ 'created': serializers.DateTimeField
+ }
+ for field_name, field in expected.items():
+ self.assertTrue(isinstance(serializer.data.fields[field_name], field))
+
+
+class ManyToManyTests(TestCase):
+ def setUp(self):
+ class ManyToManySerializer(serializers.ModelSerializer):
+ class Meta:
+ model = ManyToManyModel
+
+ self.serializer_class = ManyToManySerializer
+
+ # An anchor instance to use for the relationship
+ self.anchor = Anchor()
+ self.anchor.save()
+
+ # A model instance with a many to many relationship to the anchor
+ self.instance = ManyToManyModel()
+ self.instance.save()
+ self.instance.rel.add(self.anchor)
+
+ # A serialized representation of the model instance
+ self.data = {'id': 1, 'rel': [self.anchor.id]}
+
+ def test_retrieve(self):
+ """
+ Serialize an instance of a model with a ManyToMany relationship.
+ """
+ serializer = self.serializer_class(instance=self.instance)
+ expected = self.data
+ self.assertEquals(serializer.data, expected)
+
+ def test_create(self):
+ """
+ Create an instance of a model with a ManyToMany relationship.
+ """
+ data = {'rel': [self.anchor.id]}
+ serializer = self.serializer_class(data)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(ManyToManyModel.objects.all()), 2)
+ self.assertEquals(instance.pk, 2)
+ self.assertEquals(list(instance.rel.all()), [self.anchor])
+
+ def test_update(self):
+ """
+ Update an instance of a model with a ManyToMany relationship.
+ """
+ new_anchor = Anchor()
+ new_anchor.save()
+ data = {'rel': [self.anchor.id, new_anchor.id]}
+ serializer = self.serializer_class(data, instance=self.instance)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(ManyToManyModel.objects.all()), 1)
+ self.assertEquals(instance.pk, 1)
+ self.assertEquals(list(instance.rel.all()), [self.anchor, new_anchor])
+
+ def test_create_empty_relationship(self):
+ """
+ Create an instance of a model with a ManyToMany relationship,
+ containing no items.
+ """
+ data = {'rel': []}
+ serializer = self.serializer_class(data)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(ManyToManyModel.objects.all()), 2)
+ self.assertEquals(instance.pk, 2)
+ self.assertEquals(list(instance.rel.all()), [])
+
+ def test_update_empty_relationship(self):
+ """
+ Update an instance of a model with a ManyToMany relationship,
+ containing no items.
+ """
+ new_anchor = Anchor()
+ new_anchor.save()
+ data = {'rel': []}
+ serializer = self.serializer_class(data, instance=self.instance)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(ManyToManyModel.objects.all()), 1)
+ self.assertEquals(instance.pk, 1)
+ self.assertEquals(list(instance.rel.all()), [])
+
+ def test_create_empty_relationship_flat_data(self):
+ """
+ Create an instance of a model with a ManyToMany relationship,
+ containing no items, using a representation that does not support
+ lists (eg form data).
+ """
+ data = {'rel': ''}
+ serializer = self.serializer_class(data)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(ManyToManyModel.objects.all()), 2)
+ self.assertEquals(instance.pk, 2)
+ self.assertEquals(list(instance.rel.all()), [])
+
+
+class ReadOnlyManyToManyTests(TestCase):
+ def setUp(self):
+ class ReadOnlyManyToManySerializer(serializers.ModelSerializer):
+ rel = serializers.ManyRelatedField(read_only=True)
+
+ class Meta:
+ model = ReadOnlyManyToManyModel
+
+ self.serializer_class = ReadOnlyManyToManySerializer
+
+ # An anchor instance to use for the relationship
+ self.anchor = Anchor()
+ self.anchor.save()
+
+ # A model instance with a many to many relationship to the anchor
+ self.instance = ReadOnlyManyToManyModel()
+ self.instance.save()
+ self.instance.rel.add(self.anchor)
+
+ # A serialized representation of the model instance
+ self.data = {'rel': [self.anchor.id], 'id': 1, 'text': 'anchor'}
+
+ def test_update(self):
+ """
+ Attempt to update an instance of a model with a ManyToMany
+ relationship. Not updated due to read_only=True
+ """
+ new_anchor = Anchor()
+ new_anchor.save()
+ data = {'rel': [self.anchor.id, new_anchor.id]}
+ serializer = self.serializer_class(data, instance=self.instance)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(ReadOnlyManyToManyModel.objects.all()), 1)
+ self.assertEquals(instance.pk, 1)
+ # rel is still as original (1 entry)
+ self.assertEquals(list(instance.rel.all()), [self.anchor])
+
+ def test_update_without_relationship(self):
+ """
+ Attempt to update an instance of a model where many to ManyToMany
+ relationship is not supplied. Not updated due to read_only=True
+ """
+ new_anchor = Anchor()
+ new_anchor.save()
+ data = {}
+ serializer = self.serializer_class(data, instance=self.instance)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(ReadOnlyManyToManyModel.objects.all()), 1)
+ self.assertEquals(instance.pk, 1)
+ # rel is still as original (1 entry)
+ self.assertEquals(list(instance.rel.all()), [self.anchor])
+
+
+class DefaultValueTests(TestCase):
+ def setUp(self):
+ class DefaultValueSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = DefaultValueModel
+
+ self.serializer_class = DefaultValueSerializer
+ self.objects = DefaultValueModel.objects
+
+ def test_create_using_default(self):
+ data = {}
+ serializer = self.serializer_class(data)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(self.objects.all()), 1)
+ self.assertEquals(instance.pk, 1)
+ self.assertEquals(instance.text, 'foobar')
+
+ def test_create_overriding_default(self):
+ data = {'text': 'overridden'}
+ serializer = self.serializer_class(data)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(self.objects.all()), 1)
+ self.assertEquals(instance.pk, 1)
+ self.assertEquals(instance.text, 'overridden')
+
+
+class CallableDefaultValueTests(TestCase):
+ def setUp(self):
+ class CallableDefaultValueSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = CallableDefaultValueModel
+
+ self.serializer_class = CallableDefaultValueSerializer
+ self.objects = CallableDefaultValueModel.objects
+
+ def test_create_using_default(self):
+ data = {}
+ serializer = self.serializer_class(data)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(self.objects.all()), 1)
+ self.assertEquals(instance.pk, 1)
+ self.assertEquals(instance.text, 'foobar')
+
+ def test_create_overriding_default(self):
+ data = {'text': 'overridden'}
+ serializer = self.serializer_class(data)
+ self.assertEquals(serializer.is_valid(), True)
+ instance = serializer.save()
+ self.assertEquals(len(self.objects.all()), 1)
+ self.assertEquals(instance.pk, 1)
+ self.assertEquals(instance.text, 'overridden')
+
+
+class ManyRelatedTests(TestCase):
+ def setUp(self):
+
+ class BlogPostCommentSerializer(serializers.Serializer):
+ text = serializers.CharField()
+
+ class BlogPostSerializer(serializers.Serializer):
+ title = serializers.CharField()
+ comments = BlogPostCommentSerializer(source='blogpostcomment_set')
+
+ self.serializer_class = BlogPostSerializer
+
+ def test_reverse_relations(self):
+ post = BlogPost.objects.create(title="Test blog post")
+ post.blogpostcomment_set.create(text="I hate this blog post")
+ post.blogpostcomment_set.create(text="I love this blog post")
+
+ serializer = self.serializer_class(instance=post)
+ expected = {
+ 'title': 'Test blog post',
+ 'comments': [
+ {'text': 'I hate this blog post'},
+ {'text': 'I love this blog post'}
+ ]
+ }
+
+ self.assertEqual(serializer.data, expected)
+
+
+# Test for issue #324
+class BlankFieldTests(TestCase):
+ def setUp(self):
+
+ class BlankFieldModelSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = BlankFieldModel
+
+ class BlankFieldSerializer(serializers.Serializer):
+ title = serializers.CharField(blank=True)
+
+ class NotBlankFieldModelSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = BasicModel
+
+ class NotBlankFieldSerializer(serializers.Serializer):
+ title = serializers.CharField()
+
+ self.model_serializer_class = BlankFieldModelSerializer
+ self.serializer_class = BlankFieldSerializer
+ self.not_blank_model_serializer_class = NotBlankFieldModelSerializer
+ self.not_blank_serializer_class = NotBlankFieldSerializer
+ self.data = {'title': ''}
+
+ def test_create_blank_field(self):
+ serializer = self.serializer_class(self.data)
+ self.assertEquals(serializer.is_valid(), True)
+
+ def test_create_model_blank_field(self):
+ serializer = self.model_serializer_class(self.data)
+ self.assertEquals(serializer.is_valid(), True)
+
+ def test_create_not_blank_field(self):
+ """
+ Test to ensure blank data in a field not marked as blank=True
+ is considered invalid in a non-model serializer
+ """
+ serializer = self.not_blank_serializer_class(self.data)
+ self.assertEquals(serializer.is_valid(), False)
+
+ def test_create_model_not_blank_field(self):
+ """
+ Test to ensure blank data in a field not marked as blank=True
+ is considered invalid in a model serializer
+ """
+ serializer = self.not_blank_model_serializer_class(self.data)
+ self.assertEquals(serializer.is_valid(), False)