aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework/tests/serializer.py
diff options
context:
space:
mode:
authorTom Christie2013-03-18 21:03:05 +0000
committerTom Christie2013-03-18 21:03:05 +0000
commit74fb366c595db87bb71baeffcacfb7d2482e3a18 (patch)
tree2e28cb52542742f32cdd3fbeb625f7f59cba0a3f /rest_framework/tests/serializer.py
parent4c6396108704d38f534a16577de59178b1d0df3b (diff)
parent034c4ce4081dd6d15ea47fb8318754321a3faf0c (diff)
downloaddjango-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.py497
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)