From 9e291879d1705dea18131fc66be31e422afa1e62 Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Thu, 6 Mar 2014 15:24:07 +0100 Subject: [PATCH 1/4] Added an optional unique field to Album and checked that duplicates are detected. --- rest_framework/tests/models.py | 2 +- rest_framework/tests/test_serializer.py | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/rest_framework/tests/models.py b/rest_framework/tests/models.py index bf9883123..6c8f2342b 100644 --- a/rest_framework/tests/models.py +++ b/rest_framework/tests/models.py @@ -103,7 +103,7 @@ class BlogPostComment(RESTFrameworkModel): class Album(RESTFrameworkModel): title = models.CharField(max_length=100, unique=True) - + ref = models.CharField(max_length=10, unique=True, null=True, blank=True) class Photo(RESTFrameworkModel): description = models.TextField() diff --git a/rest_framework/tests/test_serializer.py b/rest_framework/tests/test_serializer.py index 198c269f0..17ef191a1 100644 --- a/rest_framework/tests/test_serializer.py +++ b/rest_framework/tests/test_serializer.py @@ -611,12 +611,15 @@ class ModelValidationTests(TestCase): """ Just check if serializers.ModelSerializer handles unique checks via .full_clean() """ - serializer = AlbumsSerializer(data={'title': 'a'}) + serializer = AlbumsSerializer(data={'title': 'a', 'ref': '1'}) serializer.is_valid() serializer.save() second_serializer = AlbumsSerializer(data={'title': 'a'}) self.assertFalse(second_serializer.is_valid()) - self.assertEqual(second_serializer.errors, {'title': ['Album with this Title already exists.']}) + self.assertEqual(second_serializer.errors, {'title': ['Album with this Title already exists.'],}) + third_serializer = AlbumsSerializer(data={'title': 'b', 'ref': '1'}) + self.assertFalse(third_serializer.is_valid()) + self.assertEqual(third_serializer.errors, {'ref': ['Album with this Ref already exists.'],}) def test_foreign_key_is_null_with_partial(self): """ From de899824b8352912d2a0d2fa030b8e5a053a3ae5 Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Thu, 6 Mar 2014 16:43:30 +0100 Subject: [PATCH 2/4] Forgot to add the ref field to the field list. --- rest_framework/tests/test_serializer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/tests/test_serializer.py b/rest_framework/tests/test_serializer.py index 17ef191a1..56714d1e3 100644 --- a/rest_framework/tests/test_serializer.py +++ b/rest_framework/tests/test_serializer.py @@ -161,7 +161,7 @@ class AlbumsSerializer(serializers.ModelSerializer): class Meta: model = Album - fields = ['title'] # lists are also valid options + fields = ['title', 'ref'] # lists are also valid options class PositiveIntegerAsChoiceSerializer(serializers.ModelSerializer): From caf4d36cb3484313a36453a229bfc002a075f811 Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Thu, 6 Mar 2014 21:17:41 +0100 Subject: [PATCH 3/4] More complex test case. --- rest_framework/tests/test_serializer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest_framework/tests/test_serializer.py b/rest_framework/tests/test_serializer.py index 56714d1e3..441630113 100644 --- a/rest_framework/tests/test_serializer.py +++ b/rest_framework/tests/test_serializer.py @@ -617,9 +617,9 @@ class ModelValidationTests(TestCase): second_serializer = AlbumsSerializer(data={'title': 'a'}) self.assertFalse(second_serializer.is_valid()) self.assertEqual(second_serializer.errors, {'title': ['Album with this Title already exists.'],}) - third_serializer = AlbumsSerializer(data={'title': 'b', 'ref': '1'}) + third_serializer = AlbumsSerializer(data=[{'title': 'b', 'ref': '1'}, {'title': 'c'}]) self.assertFalse(third_serializer.is_valid()) - self.assertEqual(third_serializer.errors, {'ref': ['Album with this Ref already exists.'],}) + self.assertEqual(third_serializer.errors, [{'ref': ['Album with this Ref already exists.']}, {}]) def test_foreign_key_is_null_with_partial(self): """ From 51e6982397cc032d6b3fd66f452713d448eb9084 Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Thu, 6 Mar 2014 21:18:37 +0100 Subject: [PATCH 4/4] Fixed the validation for optional fields that have a value. --- rest_framework/serializers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index c95b0593f..5c726dfcd 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -881,7 +881,7 @@ class ModelSerializer(Serializer): except KeyError: return ModelField(model_field=model_field, **kwargs) - def get_validation_exclusions(self): + def get_validation_exclusions(self, instance=None): """ Return a list of field names to exclude from model validation. """ @@ -893,7 +893,7 @@ class ModelSerializer(Serializer): field_name = field.source or field_name if field_name in exclusions \ and not field.read_only \ - and field.required \ + and (field.required or hasattr(instance, field_name)) \ and not isinstance(field, Serializer): exclusions.remove(field_name) return exclusions @@ -908,7 +908,7 @@ class ModelSerializer(Serializer): the full_clean validation checking. """ try: - instance.full_clean(exclude=self.get_validation_exclusions()) + instance.full_clean(exclude=self.get_validation_exclusions(instance)) except ValidationError as err: self._errors = err.message_dict return None