diff options
| author | Tom Christie | 2013-03-18 21:03:05 +0000 |
|---|---|---|
| committer | Tom Christie | 2013-03-18 21:03:05 +0000 |
| commit | 74fb366c595db87bb71baeffcacfb7d2482e3a18 (patch) | |
| tree | 2e28cb52542742f32cdd3fbeb625f7f59cba0a3f /rest_framework/tests/serializer.py | |
| parent | 4c6396108704d38f534a16577de59178b1d0df3b (diff) | |
| parent | 034c4ce4081dd6d15ea47fb8318754321a3faf0c (diff) | |
| download | django-rest-framework-74fb366c595db87bb71baeffcacfb7d2482e3a18.tar.bz2 | |
Merge branch 'master' into resources-routers
Diffstat (limited to 'rest_framework/tests/serializer.py')
| -rw-r--r-- | rest_framework/tests/serializer.py | 497 |
1 files changed, 353 insertions, 144 deletions
diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index bd96ba23..beb372c2 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -1,10 +1,12 @@ -import datetime -import pickle +from __future__ import unicode_literals +from django.utils.datastructures import MultiValueDict from django.test import TestCase from rest_framework import serializers from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel, BlankFieldModel, BlogPost, Book, CallableDefaultValueModel, DefaultValueModel, ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo) +import datetime +import pickle class SubComment(object): @@ -54,6 +56,19 @@ class ActionItemSerializer(serializers.ModelSerializer): model = ActionItem +class ActionItemSerializerCustomRestore(serializers.ModelSerializer): + + class Meta: + model = ActionItem + + def restore_object(self, data, instance=None): + if instance is None: + return ActionItem(**data) + for key, val in data.items(): + setattr(instance, key, val) + return instance + + class PersonSerializer(serializers.ModelSerializer): info = serializers.Field(source='info') @@ -76,6 +91,11 @@ class PositiveIntegerAsChoiceSerializer(serializers.ModelSerializer): fields = ['some_integer'] +class BrokenModelSerializer(serializers.ModelSerializer): + class Meta: + fields = ['some_field'] + + class BasicTests(TestCase): def setUp(self): self.comment = Comment( @@ -92,7 +112,7 @@ class BasicTests(TestCase): self.expected = { 'email': 'tom@example.com', 'content': 'Happy new year!', - 'created': datetime.datetime(2012, 1, 1), + 'created': '2012-01-01T00:00:00', 'sub_comment': 'And Merry Christmas!' } self.person_data = {'name': 'dwight', 'age': 35} @@ -107,39 +127,39 @@ class BasicTests(TestCase): 'created': None, 'sub_comment': '' } - self.assertEquals(serializer.data, expected) + self.assertEqual(serializer.data, expected) def test_retrieve(self): serializer = CommentSerializer(self.comment) - self.assertEquals(serializer.data, self.expected) + self.assertEqual(serializer.data, self.expected) def test_create(self): serializer = CommentSerializer(data=self.data) expected = self.comment - self.assertEquals(serializer.is_valid(), True) - self.assertEquals(serializer.object, expected) + self.assertEqual(serializer.is_valid(), True) + self.assertEqual(serializer.object, expected) self.assertFalse(serializer.object is expected) - self.assertEquals(serializer.data['sub_comment'], 'And Merry Christmas!') + self.assertEqual(serializer.data['sub_comment'], 'And Merry Christmas!') def test_update(self): serializer = CommentSerializer(self.comment, data=self.data) expected = self.comment - self.assertEquals(serializer.is_valid(), True) - self.assertEquals(serializer.object, expected) + self.assertEqual(serializer.is_valid(), True) + self.assertEqual(serializer.object, expected) self.assertTrue(serializer.object is expected) - self.assertEquals(serializer.data['sub_comment'], 'And Merry Christmas!') + self.assertEqual(serializer.data['sub_comment'], 'And Merry Christmas!') def test_partial_update(self): msg = 'Merry New Year!' partial_data = {'content': msg} serializer = CommentSerializer(self.comment, data=partial_data) - self.assertEquals(serializer.is_valid(), False) + self.assertEqual(serializer.is_valid(), False) serializer = CommentSerializer(self.comment, data=partial_data, partial=True) expected = self.comment self.assertEqual(serializer.is_valid(), True) - self.assertEquals(serializer.object, expected) + self.assertEqual(serializer.object, expected) self.assertTrue(serializer.object is expected) - self.assertEquals(serializer.data['content'], msg) + self.assertEqual(serializer.data['content'], msg) def test_model_fields_as_expected(self): """ @@ -147,7 +167,7 @@ class BasicTests(TestCase): in the Meta data """ serializer = PersonSerializer(self.person) - self.assertEquals(set(serializer.data.keys()), + self.assertEqual(set(serializer.data.keys()), set(['name', 'age', 'info'])) def test_field_with_dictionary(self): @@ -156,19 +176,45 @@ class BasicTests(TestCase): """ serializer = PersonSerializer(self.person) expected = self.person_data - self.assertEquals(serializer.data['info'], expected) + self.assertEqual(serializer.data['info'], expected) def test_read_only_fields(self): """ Attempting to update fields set as read_only should have no effect. """ - serializer = PersonSerializer(self.person, data={'name': 'dwight', 'age': 99}) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) instance = serializer.save() - self.assertEquals(serializer.errors, {}) + self.assertEqual(serializer.errors, {}) # Assert age is unchanged (35) - self.assertEquals(instance.age, self.person_data['age']) + self.assertEqual(instance.age, self.person_data['age']) + + +class DictStyleSerializer(serializers.Serializer): + """ + Note that we don't have any `restore_object` method, so the default + case of simply returning a dict will apply. + """ + email = serializers.EmailField() + + +class DictStyleSerializerTests(TestCase): + def test_dict_style_deserialize(self): + """ + Ensure serializers can deserialize into a dict. + """ + data = {'email': 'foo@example.com'} + serializer = DictStyleSerializer(data=data) + self.assertTrue(serializer.is_valid()) + self.assertEqual(serializer.data, data) + + def test_dict_style_serialize(self): + """ + Ensure serializers can serialize dict objects. + """ + data = {'email': 'foo@example.com'} + serializer = DictStyleSerializer(data) + self.assertEqual(serializer.data, data) class ValidationTests(TestCase): @@ -183,18 +229,17 @@ class ValidationTests(TestCase): 'content': 'x' * 1001, 'created': datetime.datetime(2012, 1, 1) } - self.actionitem = ActionItem(title='Some to do item', - ) + self.actionitem = ActionItem(title='Some to do item',) def test_create(self): serializer = CommentSerializer(data=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).']}) + self.assertEqual(serializer.is_valid(), False) + self.assertEqual(serializer.errors, {'content': ['Ensure this value has at most 1000 characters (it has 1001).']}) def test_update(self): serializer = CommentSerializer(self.comment, data=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).']}) + self.assertEqual(serializer.is_valid(), False) + self.assertEqual(serializer.errors, {'content': ['Ensure this value has at most 1000 characters (it has 1001).']}) def test_update_missing_field(self): data = { @@ -202,8 +247,8 @@ class ValidationTests(TestCase): 'created': datetime.datetime(2012, 1, 1) } serializer = CommentSerializer(self.comment, data=data) - self.assertEquals(serializer.is_valid(), False) - self.assertEquals(serializer.errors, {'email': [u'This field is required.']}) + self.assertEqual(serializer.is_valid(), False) + self.assertEqual(serializer.errors, {'email': ['This field is required.']}) def test_missing_bool_with_default(self): """Make sure that a boolean value with a 'False' value is not @@ -213,52 +258,36 @@ class ValidationTests(TestCase): #No 'done' value. } serializer = ActionItemSerializer(self.actionitem, data=data) - 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=data) - self.assertTrue(serializer.is_valid()) - - data['content'] = 'This should not validate' - - serializer = CommentSerializerWithFieldValidator(data=data) - self.assertFalse(serializer.is_valid()) - self.assertEquals(serializer.errors, {'content': [u'Test not in value']}) + self.assertEqual(serializer.is_valid(), True) + self.assertEqual(serializer.errors, {}) def test_bad_type_data_is_false(self): """ Data of the wrong type is not valid. """ data = ['i am', 'a', 'list'] - serializer = CommentSerializer(self.comment, data=data) - self.assertEquals(serializer.is_valid(), False) - self.assertEquals(serializer.errors, {'non_field_errors': [u'Invalid data']}) + serializer = CommentSerializer(self.comment, data=data, many=True) + self.assertEqual(serializer.is_valid(), False) + self.assertTrue(isinstance(serializer.errors, list)) + + self.assertEqual( + serializer.errors, + [ + {'non_field_errors': ['Invalid data']}, + {'non_field_errors': ['Invalid data']}, + {'non_field_errors': ['Invalid data']} + ] + ) data = 'and i am a string' serializer = CommentSerializer(self.comment, data=data) - self.assertEquals(serializer.is_valid(), False) - self.assertEquals(serializer.errors, {'non_field_errors': [u'Invalid data']}) + self.assertEqual(serializer.is_valid(), False) + self.assertEqual(serializer.errors, {'non_field_errors': ['Invalid data']}) data = 42 serializer = CommentSerializer(self.comment, data=data) - self.assertEquals(serializer.is_valid(), False) - self.assertEquals(serializer.errors, {'non_field_errors': [u'Invalid data']}) + self.assertEqual(serializer.is_valid(), False) + self.assertEqual(serializer.errors, {'non_field_errors': ['Invalid data']}) def test_cross_field_validation(self): @@ -282,23 +311,37 @@ class ValidationTests(TestCase): serializer = CommentSerializerWithCrossFieldValidator(data=data) self.assertFalse(serializer.is_valid()) - self.assertEquals(serializer.errors, {'non_field_errors': [u'Email address not in content']}) + self.assertEqual(serializer.errors, {'non_field_errors': ['Email address not in content']}) def test_null_is_true_fields(self): """ Omitting a value for null-field should validate. """ serializer = PersonSerializer(data={'name': 'marko'}) - self.assertEquals(serializer.is_valid(), True) - self.assertEquals(serializer.errors, {}) + self.assertEqual(serializer.is_valid(), True) + self.assertEqual(serializer.errors, {}) def test_modelserializer_max_length_exceeded(self): data = { 'title': 'x' * 201, } serializer = ActionItemSerializer(data=data) - self.assertEquals(serializer.is_valid(), False) - self.assertEquals(serializer.errors, {'title': [u'Ensure this value has at most 200 characters (it has 201).']}) + self.assertEqual(serializer.is_valid(), False) + self.assertEqual(serializer.errors, {'title': ['Ensure this value has at most 200 characters (it has 201).']}) + + def test_modelserializer_max_length_exceeded_with_custom_restore(self): + """ + When overriding ModelSerializer.restore_object, validation tests should still apply. + Regression test for #623. + + https://github.com/tomchristie/django-rest-framework/pull/623 + """ + data = { + 'title': 'x' * 201, + } + serializer = ActionItemSerializerCustomRestore(data=data) + self.assertEqual(serializer.is_valid(), False) + self.assertEqual(serializer.errors, {'title': ['Ensure this value has at most 200 characters (it has 201).']}) def test_default_modelfield_max_length_exceeded(self): data = { @@ -306,15 +349,99 @@ class ValidationTests(TestCase): 'info': 'x' * 13, } serializer = ActionItemSerializer(data=data) - self.assertEquals(serializer.is_valid(), False) - self.assertEquals(serializer.errors, {'info': [u'Ensure this value has at most 12 characters (it has 13).']}) + self.assertEqual(serializer.is_valid(), False) + self.assertEqual(serializer.errors, {'info': ['Ensure this value has at most 12 characters (it has 13).']}) + + def test_datetime_validation_failure(self): + """ + Test DateTimeField validation errors on non-str values. + Regression test for #669. + + https://github.com/tomchristie/django-rest-framework/issues/669 + """ + data = self.data + data['created'] = 0 + + serializer = CommentSerializer(data=data) + self.assertEqual(serializer.is_valid(), False) + + self.assertIn('created', serializer.errors) + + def test_missing_model_field_exception_msg(self): + """ + Assert that a meaningful exception message is outputted when the model + field is missing (e.g. when mistyping ``model``). + """ + try: + serializer = BrokenModelSerializer() + except AssertionError as e: + self.assertEqual(e.args[0], "Serializer class 'BrokenModelSerializer' is missing 'model' Meta option") + except: + self.fail('Wrong exception type thrown.') + + +class CustomValidationTests(TestCase): + class CommentSerializerWithFieldValidator(CommentSerializer): + + def validate_email(self, attrs, source): + value = attrs[source] + + return attrs + + def validate_content(self, attrs, source): + value = attrs[source] + if "test" not in value: + raise serializers.ValidationError("Test not in value") + return attrs + + def test_field_validation(self): + data = { + 'email': 'tom@example.com', + 'content': 'A test comment', + 'created': datetime.datetime(2012, 1, 1) + } + + serializer = self.CommentSerializerWithFieldValidator(data=data) + self.assertTrue(serializer.is_valid()) + + data['content'] = 'This should not validate' + + serializer = self.CommentSerializerWithFieldValidator(data=data) + self.assertFalse(serializer.is_valid()) + self.assertEqual(serializer.errors, {'content': ['Test not in value']}) + + def test_missing_data(self): + """ + Make sure that validate_content isn't called if the field is missing + """ + incomplete_data = { + 'email': 'tom@example.com', + 'created': datetime.datetime(2012, 1, 1) + } + serializer = self.CommentSerializerWithFieldValidator(data=incomplete_data) + self.assertFalse(serializer.is_valid()) + self.assertEqual(serializer.errors, {'content': ['This field is required.']}) + + def test_wrong_data(self): + """ + Make sure that validate_content isn't called if the field input is wrong + """ + wrong_data = { + 'email': 'not an email', + 'content': 'A test comment', + 'created': datetime.datetime(2012, 1, 1) + } + serializer = self.CommentSerializerWithFieldValidator(data=wrong_data) + self.assertFalse(serializer.is_valid()) + self.assertEqual(serializer.errors, {'email': ['Enter a valid e-mail address.']}) class PositiveIntegerAsChoiceTests(TestCase): def test_positive_integer_in_json_is_correctly_parsed(self): - data = {'some_integer':1} + data = {'some_integer': 1} serializer = PositiveIntegerAsChoiceSerializer(data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) + class ModelValidationTests(TestCase): def test_validate_unique(self): @@ -326,7 +453,7 @@ class ModelValidationTests(TestCase): serializer.save() second_serializer = AlbumsSerializer(data={'title': 'a'}) self.assertFalse(second_serializer.is_valid()) - self.assertEqual(second_serializer.errors, {'title': [u'Album with this Title already exists.']}) + self.assertEqual(second_serializer.errors, {'title': ['Album with this Title already exists.']}) def test_foreign_key_with_partial(self): """ @@ -364,15 +491,15 @@ class RegexValidationTest(TestCase): def test_create_failed(self): serializer = BookSerializer(data={'isbn': '1234567890'}) self.assertFalse(serializer.is_valid()) - self.assertEquals(serializer.errors, {'isbn': [u'isbn has to be exact 13 numbers']}) + self.assertEqual(serializer.errors, {'isbn': ['isbn has to be exact 13 numbers']}) serializer = BookSerializer(data={'isbn': '12345678901234'}) self.assertFalse(serializer.is_valid()) - self.assertEquals(serializer.errors, {'isbn': [u'isbn has to be exact 13 numbers']}) + self.assertEqual(serializer.errors, {'isbn': ['isbn has to be exact 13 numbers']}) serializer = BookSerializer(data={'isbn': 'abcdefghijklm'}) self.assertFalse(serializer.is_valid()) - self.assertEquals(serializer.errors, {'isbn': [u'isbn has to be exact 13 numbers']}) + self.assertEqual(serializer.errors, {'isbn': ['isbn has to be exact 13 numbers']}) def test_create_success(self): serializer = BookSerializer(data={'isbn': '1234567890123'}) @@ -417,7 +544,7 @@ class ManyToManyTests(TestCase): """ serializer = self.serializer_class(instance=self.instance) expected = self.data - self.assertEquals(serializer.data, expected) + self.assertEqual(serializer.data, expected) def test_create(self): """ @@ -425,11 +552,11 @@ class ManyToManyTests(TestCase): """ data = {'rel': [self.anchor.id]} serializer = self.serializer_class(data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(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]) + self.assertEqual(len(ManyToManyModel.objects.all()), 2) + self.assertEqual(instance.pk, 2) + self.assertEqual(list(instance.rel.all()), [self.anchor]) def test_update(self): """ @@ -439,11 +566,11 @@ class ManyToManyTests(TestCase): new_anchor.save() data = {'rel': [self.anchor.id, new_anchor.id]} serializer = self.serializer_class(self.instance, data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(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]) + self.assertEqual(len(ManyToManyModel.objects.all()), 1) + self.assertEqual(instance.pk, 1) + self.assertEqual(list(instance.rel.all()), [self.anchor, new_anchor]) def test_create_empty_relationship(self): """ @@ -452,11 +579,11 @@ class ManyToManyTests(TestCase): """ data = {'rel': []} serializer = self.serializer_class(data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(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.assertEqual(len(ManyToManyModel.objects.all()), 2) + self.assertEqual(instance.pk, 2) + self.assertEqual(list(instance.rel.all()), []) def test_update_empty_relationship(self): """ @@ -467,11 +594,11 @@ class ManyToManyTests(TestCase): new_anchor.save() data = {'rel': []} serializer = self.serializer_class(self.instance, data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(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.assertEqual(len(ManyToManyModel.objects.all()), 1) + self.assertEqual(instance.pk, 1) + self.assertEqual(list(instance.rel.all()), []) def test_create_empty_relationship_flat_data(self): """ @@ -479,19 +606,20 @@ class ManyToManyTests(TestCase): containing no items, using a representation that does not support lists (eg form data). """ - data = {'rel': ''} + data = MultiValueDict() + data.setlist('rel', ['']) serializer = self.serializer_class(data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(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.assertEqual(len(ManyToManyModel.objects.all()), 2) + self.assertEqual(instance.pk, 2) + self.assertEqual(list(instance.rel.all()), []) class ReadOnlyManyToManyTests(TestCase): def setUp(self): class ReadOnlyManyToManySerializer(serializers.ModelSerializer): - rel = serializers.ManyRelatedField(read_only=True) + rel = serializers.RelatedField(many=True, read_only=True) class Meta: model = ReadOnlyManyToManyModel @@ -519,12 +647,12 @@ class ReadOnlyManyToManyTests(TestCase): new_anchor.save() data = {'rel': [self.anchor.id, new_anchor.id]} serializer = self.serializer_class(self.instance, data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) instance = serializer.save() - self.assertEquals(len(ReadOnlyManyToManyModel.objects.all()), 1) - self.assertEquals(instance.pk, 1) + self.assertEqual(len(ReadOnlyManyToManyModel.objects.all()), 1) + self.assertEqual(instance.pk, 1) # rel is still as original (1 entry) - self.assertEquals(list(instance.rel.all()), [self.anchor]) + self.assertEqual(list(instance.rel.all()), [self.anchor]) def test_update_without_relationship(self): """ @@ -535,12 +663,12 @@ class ReadOnlyManyToManyTests(TestCase): new_anchor.save() data = {} serializer = self.serializer_class(self.instance, data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) instance = serializer.save() - self.assertEquals(len(ReadOnlyManyToManyModel.objects.all()), 1) - self.assertEquals(instance.pk, 1) + self.assertEqual(len(ReadOnlyManyToManyModel.objects.all()), 1) + self.assertEqual(instance.pk, 1) # rel is still as original (1 entry) - self.assertEquals(list(instance.rel.all()), [self.anchor]) + self.assertEqual(list(instance.rel.all()), [self.anchor]) class DefaultValueTests(TestCase): @@ -555,35 +683,35 @@ class DefaultValueTests(TestCase): def test_create_using_default(self): data = {} serializer = self.serializer_class(data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) instance = serializer.save() - self.assertEquals(len(self.objects.all()), 1) - self.assertEquals(instance.pk, 1) - self.assertEquals(instance.text, 'foobar') + self.assertEqual(len(self.objects.all()), 1) + self.assertEqual(instance.pk, 1) + self.assertEqual(instance.text, 'foobar') def test_create_overriding_default(self): data = {'text': 'overridden'} serializer = self.serializer_class(data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) instance = serializer.save() - self.assertEquals(len(self.objects.all()), 1) - self.assertEquals(instance.pk, 1) - self.assertEquals(instance.text, 'overridden') + self.assertEqual(len(self.objects.all()), 1) + self.assertEqual(instance.pk, 1) + self.assertEqual(instance.text, 'overridden') def test_partial_update_default(self): """ Regression test for issue #532 """ data = {'text': 'overridden'} serializer = self.serializer_class(data=data, partial=True) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) instance = serializer.save() data = {'extra': 'extra_value'} serializer = self.serializer_class(instance=instance, data=data, partial=True) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) instance = serializer.save() - self.assertEquals(instance.extra, 'extra_value') - self.assertEquals(instance.text, 'overridden') + self.assertEqual(instance.extra, 'extra_value') + self.assertEqual(instance.text, 'overridden') class CallableDefaultValueTests(TestCase): @@ -598,20 +726,20 @@ class CallableDefaultValueTests(TestCase): def test_create_using_default(self): data = {} serializer = self.serializer_class(data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) instance = serializer.save() - self.assertEquals(len(self.objects.all()), 1) - self.assertEquals(instance.pk, 1) - self.assertEquals(instance.text, 'foobar') + self.assertEqual(len(self.objects.all()), 1) + self.assertEqual(instance.pk, 1) + self.assertEqual(instance.text, 'foobar') def test_create_overriding_default(self): data = {'text': 'overridden'} serializer = self.serializer_class(data=data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) instance = serializer.save() - self.assertEquals(len(self.objects.all()), 1) - self.assertEquals(instance.pk, 1) - self.assertEquals(instance.text, 'overridden') + self.assertEqual(len(self.objects.all()), 1) + self.assertEqual(instance.pk, 1) + self.assertEqual(instance.text, 'overridden') class ManyRelatedTests(TestCase): @@ -660,6 +788,9 @@ class ManyRelatedTests(TestCase): class RelatedTraversalTest(TestCase): def test_nested_traversal(self): + """ + Source argument should support dotted.source notation. + """ user = Person.objects.create(name="django") post = BlogPost.objects.create(title="Test blog post", writer=user) post.blogpostcomment_set.create(text="I love this blog post") @@ -686,11 +817,11 @@ class RelatedTraversalTest(TestCase): serializer = BlogPostSerializer(instance=post) expected = { - 'title': u'Test blog post', + 'title': 'Test blog post', 'comments': [{ - 'text': u'I love this blog post', + 'text': 'I love this blog post', 'post_owner': { - "name": u"django", + "name": "django", "age": None } }] @@ -698,6 +829,41 @@ class RelatedTraversalTest(TestCase): self.assertEqual(serializer.data, expected) + def test_nested_traversal_with_none(self): + """ + If a component of the dotted.source is None, return None for the field. + """ + from rest_framework.tests.models import NullableForeignKeySource + instance = NullableForeignKeySource.objects.create(name='Source with null FK') + + class NullableSourceSerializer(serializers.Serializer): + target_name = serializers.Field(source='target.name') + + serializer = NullableSourceSerializer(instance=instance) + + expected = { + 'target_name': None, + } + + self.assertEqual(serializer.data, expected) + + def test_queryset_nested_traversal(self): + """ + Relational fields should be able to use methods as their source. + """ + BlogPost.objects.create(title='blah') + + class QuerysetMethodSerializer(serializers.Serializer): + blogposts = serializers.RelatedField(many=True, source='get_all_blogposts') + + class ClassWithQuerysetMethod(object): + def get_all_blogposts(self): + return BlogPost.objects + + obj = ClassWithQuerysetMethod() + serializer = QuerysetMethodSerializer(obj) + self.assertEqual(serializer.data, {'blogposts': ['BlogPost object']}) + class SerializerMethodFieldTests(TestCase): def setUp(self): @@ -725,8 +891,8 @@ class SerializerMethodFieldTests(TestCase): serializer = self.serializer_class(source_data) expected = { - 'beep': u'hello!', - 'boop': [u'a', u'b', u'c'], + 'beep': 'hello!', + 'boop': ['a', 'b', 'c'], 'boop_count': 3, } @@ -742,7 +908,7 @@ class BlankFieldTests(TestCase): model = BlankFieldModel class BlankFieldSerializer(serializers.Serializer): - title = serializers.CharField(blank=True) + title = serializers.CharField(required=False) class NotBlankFieldModelSerializer(serializers.ModelSerializer): class Meta: @@ -759,15 +925,15 @@ class BlankFieldTests(TestCase): def test_create_blank_field(self): serializer = self.serializer_class(data=self.data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) def test_create_model_blank_field(self): serializer = self.model_serializer_class(data=self.data) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) def test_create_model_null_field(self): serializer = self.model_serializer_class(data={'title': None}) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) def test_create_not_blank_field(self): """ @@ -775,7 +941,7 @@ class BlankFieldTests(TestCase): is considered invalid in a non-model serializer """ serializer = self.not_blank_serializer_class(data=self.data) - self.assertEquals(serializer.is_valid(), False) + self.assertEqual(serializer.is_valid(), False) def test_create_model_not_blank_field(self): """ @@ -783,11 +949,11 @@ class BlankFieldTests(TestCase): is considered invalid in a model serializer """ serializer = self.not_blank_model_serializer_class(data=self.data) - self.assertEquals(serializer.is_valid(), False) + self.assertEqual(serializer.is_valid(), False) - def test_create_model_null_field(self): + def test_create_model_empty_field(self): serializer = self.model_serializer_class(data={}) - self.assertEquals(serializer.is_valid(), True) + self.assertEqual(serializer.is_valid(), True) #test for issue #460 @@ -811,7 +977,21 @@ class SerializerPickleTests(TestCase): class Meta: model = Person fields = ('name', 'age') - pickle.dumps(InnerPersonSerializer(Person(name="Noah", age=950)).data) + pickle.dumps(InnerPersonSerializer(Person(name="Noah", age=950)).data, 0) + + def test_getstate_method_should_not_return_none(self): + """ + Regression test for #645. + """ + data = serializers.DictWithMetadata({1: 1}) + self.assertEqual(data.__getstate__(), serializers.SortedDict({1: 1})) + + def test_serializer_data_is_pickleable(self): + """ + Another regression test for #645. + """ + data = serializers.SortedDictWithMetadata({1: 1}) + repr(pickle.loads(pickle.dumps(data, 0))) class DepthTest(TestCase): @@ -825,8 +1005,8 @@ class DepthTest(TestCase): depth = 1 serializer = BlogPostSerializer(instance=post) - expected = {'id': 1, 'title': u'Test blog post', - 'writer': {'id': 1, 'name': u'django', 'age': 1}} + expected = {'id': 1, 'title': 'Test blog post', + 'writer': {'id': 1, 'name': 'django', 'age': 1}} self.assertEqual(serializer.data, expected) @@ -845,8 +1025,8 @@ class DepthTest(TestCase): model = BlogPost serializer = BlogPostSerializer(instance=post) - expected = {'id': 1, 'title': u'Test blog post', - 'writer': {'id': 1, 'name': u'django', 'age': 1}} + expected = {'id': 1, 'title': 'Test blog post', + 'writer': {'id': 1, 'name': 'django', 'age': 1}} self.assertEqual(serializer.data, expected) @@ -901,3 +1081,32 @@ class NestedSerializerContextTests(TestCase): # This will raise RuntimeError if context doesn't get passed correctly to the nested Serializers AlbumCollectionSerializer(album_collection, context={'context_item': 'album context'}).data + + +class DeserializeListTestCase(TestCase): + + def setUp(self): + self.data = { + 'email': 'nobody@nowhere.com', + 'content': 'This is some test content', + 'created': datetime.datetime(2013, 3, 7), + } + + def test_no_errors(self): + data = [self.data.copy() for x in range(0, 3)] + serializer = CommentSerializer(data=data) + self.assertTrue(serializer.is_valid()) + self.assertTrue(isinstance(serializer.object, list)) + self.assertTrue( + all((isinstance(item, Comment) for item in serializer.object)) + ) + + def test_errors_return_as_list(self): + invalid_item = self.data.copy() + invalid_item['email'] = '' + data = [self.data.copy(), invalid_item, self.data.copy()] + + serializer = CommentSerializer(data=data) + self.assertFalse(serializer.is_valid()) + expected = [{}, {'email': ['This field is required.']}, {}] + self.assertEqual(serializer.errors, expected) |
