Skip to content

Commit a4a3093

Browse files
committed
Add test to demonstrate that uniquetoghetervalidator does not enforce partial unique-constraint against FKs
1 parent 0f57622 commit a4a3093

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

tests/test_validators.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import pytest
66
from django import VERSION as django_version
7+
from django.core.exceptions import ValidationError as DjangoValidationError
78
from django.db import DataError, models
89
from django.test import TestCase
910

@@ -779,6 +780,75 @@ class Meta:
779780
assert serializer.is_valid()
780781

781782

783+
class UniqueConstraintWithRelationModel(models.Model):
784+
value = models.IntegerField()
785+
first_related = models.ForeignKey(IntegerFieldModel, related_name='+', on_delete=models.CASCADE, null=True, blank=True)
786+
second_related = models.ForeignKey(IntegerFieldModel, related_name='+', on_delete=models.CASCADE, null=True, blank=True)
787+
788+
class Meta:
789+
constraints = [
790+
models.UniqueConstraint(fields=('value', 'first_related'), condition=models.Q(second_related__isnull=True), name='unique_constraint_with_relationa'),
791+
models.UniqueConstraint(fields=('value', 'second_related'), condition=models.Q(first_related__isnull=True), name='unique_constraint_with_relationb'),
792+
]
793+
794+
795+
class UniqueConstraintWithRelationModelSerializer(serializers.ModelSerializer):
796+
class Meta:
797+
model = UniqueConstraintWithRelationModel
798+
fields = serializers.ALL_FIELDS
799+
800+
801+
class TestUniqueConstraintWithRelationValidation(TestCase):
802+
def setUp(self):
803+
self.related_model = IntegerFieldModel.objects.create(integer=1)
804+
self.instance_first = UniqueConstraintWithRelationModel.objects.create(
805+
value=1,
806+
first_related=self.related_model,
807+
second_related=None
808+
)
809+
self.instance_second = UniqueConstraintWithRelationModel.objects.create(
810+
value=1,
811+
first_related=None,
812+
second_related=self.related_model
813+
)
814+
815+
def test_unique_constraint_with_relation_first(self):
816+
instance = UniqueConstraintWithRelationModel(value=1, first_related=self.related_model, second_related=None)
817+
with pytest.raises(DjangoValidationError) as excinfo:
818+
instance.validate_constraints()
819+
820+
assert str(excinfo.value) == "{'__all__': ['Constraint “unique_constraint_with_relationa” is violated.']}"
821+
serializer = UniqueConstraintWithRelationModelSerializer(data={
822+
'value': 1,
823+
'first_related': self.related_model.pk,
824+
'second_related': None
825+
})
826+
assert not serializer.is_valid()
827+
assert serializer.errors == {
828+
'non_field_errors': [
829+
'The fields value, first_related must make a unique set.'
830+
]
831+
}
832+
833+
def test_unique_constraint_with_relation_second(self):
834+
instance = UniqueConstraintWithRelationModel(value=1, second_related=self.related_model, first_related=None)
835+
with pytest.raises(DjangoValidationError) as excinfo:
836+
instance.validate_constraints()
837+
838+
assert str(excinfo.value) == "{'__all__': ['Constraint “unique_constraint_with_relationb” is violated.']}"
839+
serializer = UniqueConstraintWithRelationModelSerializer(data={
840+
'value': 1,
841+
'first_related': None,
842+
'second_related': self.related_model.pk
843+
})
844+
assert not serializer.is_valid()
845+
assert serializer.errors == {
846+
'non_field_errors': [
847+
'The fields value, second_related must make a unique set.'
848+
]
849+
}
850+
851+
782852
# Tests for `UniqueForDateValidator`
783853
# ----------------------------------
784854

0 commit comments

Comments
 (0)