mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-03-06 12:26:00 +03:00
Fix raising on nullable fields part of UniqueConstraint
(#9531)
* Add test to reproduce problem with nullable fields part of a unique constraint Ref #9378 * Simplify test case and add similar case for unique_together * Add test for unique together in a better place * Default nullable fields to null in unique constraints checks * Remove redundant test and move other to more appropriate place
This commit is contained in:
parent
dbac145638
commit
a8595a8eae
|
@ -1490,6 +1490,8 @@ class ModelSerializer(Serializer):
|
||||||
default = timezone.now
|
default = timezone.now
|
||||||
elif unique_constraint_field.has_default():
|
elif unique_constraint_field.has_default():
|
||||||
default = unique_constraint_field.default
|
default = unique_constraint_field.default
|
||||||
|
elif unique_constraint_field.null:
|
||||||
|
default = None
|
||||||
else:
|
else:
|
||||||
default = empty
|
default = empty
|
||||||
|
|
||||||
|
|
|
@ -441,6 +441,14 @@ class TestUniquenessTogetherValidation(TestCase):
|
||||||
serializer = NullUniquenessTogetherSerializer(data=data)
|
serializer = NullUniquenessTogetherSerializer(data=data)
|
||||||
assert serializer.is_valid()
|
assert serializer.is_valid()
|
||||||
|
|
||||||
|
def test_ignore_validation_for_missing_nullable_fields(self):
|
||||||
|
data = {
|
||||||
|
'date': datetime.date(2000, 1, 1),
|
||||||
|
'race_name': 'Paris Marathon',
|
||||||
|
}
|
||||||
|
serializer = NullUniquenessTogetherSerializer(data=data)
|
||||||
|
assert serializer.is_valid(), serializer.errors
|
||||||
|
|
||||||
def test_do_not_ignore_validation_for_null_fields(self):
|
def test_do_not_ignore_validation_for_null_fields(self):
|
||||||
# None values that are not on fields part of the uniqueness constraint
|
# None values that are not on fields part of the uniqueness constraint
|
||||||
# do not cause the instance to skip validation.
|
# do not cause the instance to skip validation.
|
||||||
|
@ -539,12 +547,30 @@ class UniqueConstraintModel(models.Model):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class UniqueConstraintNullableModel(models.Model):
|
||||||
|
title = models.CharField(max_length=100)
|
||||||
|
age = models.IntegerField(null=True)
|
||||||
|
tag = models.CharField(max_length=100, null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
constraints = [
|
||||||
|
# Unique constraint on 2 nullable fields
|
||||||
|
models.UniqueConstraint(name='unique_constraint', fields=('age', 'tag'))
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class UniqueConstraintSerializer(serializers.ModelSerializer):
|
class UniqueConstraintSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UniqueConstraintModel
|
model = UniqueConstraintModel
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class UniqueConstraintNullableSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = UniqueConstraintNullableModel
|
||||||
|
fields = ('title', 'age', 'tag')
|
||||||
|
|
||||||
|
|
||||||
class TestUniqueConstraintValidation(TestCase):
|
class TestUniqueConstraintValidation(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.instance = UniqueConstraintModel.objects.create(
|
self.instance = UniqueConstraintModel.objects.create(
|
||||||
|
@ -611,6 +637,12 @@ class TestUniqueConstraintValidation(TestCase):
|
||||||
ids_in_qs = {frozenset(v.queryset.values_list(flat=True)) for v in validators if hasattr(v, "queryset")}
|
ids_in_qs = {frozenset(v.queryset.values_list(flat=True)) for v in validators if hasattr(v, "queryset")}
|
||||||
assert ids_in_qs == {frozenset([1]), frozenset([3])}
|
assert ids_in_qs == {frozenset([1]), frozenset([3])}
|
||||||
|
|
||||||
|
def test_nullable_unique_constraint_fields_are_not_required(self):
|
||||||
|
serializer = UniqueConstraintNullableSerializer(data={'title': 'Bob'})
|
||||||
|
self.assertTrue(serializer.is_valid(), serializer.errors)
|
||||||
|
result = serializer.save()
|
||||||
|
self.assertIsInstance(result, UniqueConstraintNullableModel)
|
||||||
|
|
||||||
|
|
||||||
# Tests for `UniqueForDateValidator`
|
# Tests for `UniqueForDateValidator`
|
||||||
# ----------------------------------
|
# ----------------------------------
|
||||||
|
|
Loading…
Reference in New Issue
Block a user