Merge pull request #1459 from linovia/bugfix/optional_unique_validation

Unique constraint are validated even if the field is optional.
This commit is contained in:
Carlton Gibson 2014-03-06 22:48:16 +01:00
commit d48e8ca8d6
3 changed files with 10 additions and 7 deletions

View File

@ -881,7 +881,7 @@ class ModelSerializer(Serializer):
except KeyError: except KeyError:
return ModelField(model_field=model_field, **kwargs) 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. 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 field_name = field.source or field_name
if field_name in exclusions \ if field_name in exclusions \
and not field.read_only \ and not field.read_only \
and field.required \ and (field.required or hasattr(instance, field_name)) \
and not isinstance(field, Serializer): and not isinstance(field, Serializer):
exclusions.remove(field_name) exclusions.remove(field_name)
return exclusions return exclusions
@ -908,7 +908,7 @@ class ModelSerializer(Serializer):
the full_clean validation checking. the full_clean validation checking.
""" """
try: try:
instance.full_clean(exclude=self.get_validation_exclusions()) instance.full_clean(exclude=self.get_validation_exclusions(instance))
except ValidationError as err: except ValidationError as err:
self._errors = err.message_dict self._errors = err.message_dict
return None return None

View File

@ -103,7 +103,7 @@ class BlogPostComment(RESTFrameworkModel):
class Album(RESTFrameworkModel): class Album(RESTFrameworkModel):
title = models.CharField(max_length=100, unique=True) title = models.CharField(max_length=100, unique=True)
ref = models.CharField(max_length=10, unique=True, null=True, blank=True)
class Photo(RESTFrameworkModel): class Photo(RESTFrameworkModel):
description = models.TextField() description = models.TextField()

View File

@ -161,7 +161,7 @@ class AlbumsSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Album model = Album
fields = ['title'] # lists are also valid options fields = ['title', 'ref'] # lists are also valid options
class PositiveIntegerAsChoiceSerializer(serializers.ModelSerializer): class PositiveIntegerAsChoiceSerializer(serializers.ModelSerializer):
@ -611,12 +611,15 @@ class ModelValidationTests(TestCase):
""" """
Just check if serializers.ModelSerializer handles unique checks via .full_clean() 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.is_valid()
serializer.save() serializer.save()
second_serializer = AlbumsSerializer(data={'title': 'a'}) second_serializer = AlbumsSerializer(data={'title': 'a'})
self.assertFalse(second_serializer.is_valid()) 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'}, {'title': 'c'}])
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): def test_foreign_key_is_null_with_partial(self):
""" """