This commit is contained in:
Sergei Shishov 2025-08-10 19:52:36 +09:00 committed by GitHub
commit 5ffd1481dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 68 additions and 0 deletions

View File

@ -1496,6 +1496,8 @@ class ModelSerializer(Serializer):
default = unique_constraint_field.default
elif unique_constraint_field.null:
default = None
elif unique_constraint_field.blank:
default = ''
else:
default = empty

View File

@ -149,6 +149,14 @@ class UniquenessTogetherModel(models.Model):
unique_together = ('race_name', 'position')
class BlankUniquenessTogetherModel(models.Model):
race_name = models.CharField(max_length=100, blank=True)
position = models.IntegerField()
class Meta:
unique_together = ('race_name', 'position')
class NullUniquenessTogetherModel(models.Model):
"""
Used to ensure that null values are not included when checking
@ -176,6 +184,12 @@ class UniquenessTogetherSerializer(serializers.ModelSerializer):
fields = '__all__'
class BlankUniquenessTogetherSerializer(serializers.ModelSerializer):
class Meta:
model = BlankUniquenessTogetherModel
fields = '__all__'
class NullUniquenessTogetherSerializer(serializers.ModelSerializer):
class Meta:
model = NullUniquenessTogetherModel
@ -461,6 +475,34 @@ class TestUniquenessTogetherValidation(TestCase):
serializer = NullUniquenessTogetherSerializer(data=data)
assert not serializer.is_valid()
def test_validation_for_provided_blank_fields(self):
BlankUniquenessTogetherModel.objects.create(
position=1
)
data = {
'race_name': '',
'position': 1
}
serializer = BlankUniquenessTogetherSerializer(data=data)
assert not serializer.is_valid()
def test_validation_for_missing_blank_fields(self):
BlankUniquenessTogetherModel.objects.create(
position=1
)
data = {
'position': 1
}
serializer = BlankUniquenessTogetherSerializer(data=data)
assert not serializer.is_valid()
def test_ignore_validation_for_missing_blank_fields(self):
data = {
'position': 1
}
serializer = BlankUniquenessTogetherSerializer(data=data)
assert serializer.is_valid(), serializer.errors
def test_ignore_validation_for_unchanged_fields(self):
"""
If all fields in the unique together constraint are unchanged,
@ -589,6 +631,18 @@ class UniqueConstraintModel(models.Model):
]
class UniqueConstraintBlankModel(models.Model):
title = models.CharField(max_length=100, blank=True)
age = models.IntegerField()
tag = models.CharField(max_length=100, blank=True)
class Meta:
constraints = [
# Unique constraint on 2 blank fields
models.UniqueConstraint(name='unique_constraint', fields=('age', 'tag'), condition=~models.Q(models.Q(title='') & models.Q(tag='True')))
]
class UniqueConstraintNullableModel(models.Model):
title = models.CharField(max_length=100)
age = models.IntegerField(null=True)
@ -607,6 +661,12 @@ class UniqueConstraintSerializer(serializers.ModelSerializer):
fields = '__all__'
class UniqueConstraintBlankSerializer(serializers.ModelSerializer):
class Meta:
model = UniqueConstraintBlankModel
fields = ('title', 'age', 'tag')
class UniqueConstraintNullableSerializer(serializers.ModelSerializer):
class Meta:
model = UniqueConstraintNullableModel
@ -714,6 +774,12 @@ class TestUniqueConstraintValidation(TestCase):
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])}
def test_blank_uqnique_constraint_fields_are_not_required(self):
serializer = UniqueConstraintBlankSerializer(data={'age': 25})
self.assertTrue(serializer.is_valid(), serializer.errors)
result = serializer.save()
self.assertIsInstance(result, UniqueConstraintBlankModel)
def test_nullable_unique_constraint_fields_are_not_required(self):
serializer = UniqueConstraintNullableSerializer(data={'title': 'Bob'})
self.assertTrue(serializer.is_valid(), serializer.errors)