|
4 | 4 |
|
5 | 5 | import pytest
|
6 | 6 | from django import VERSION as django_version
|
| 7 | +from django.core.exceptions import ValidationError as DjangoValidationError |
7 | 8 | from django.db import DataError, models
|
8 | 9 | from django.test import TestCase
|
9 | 10 |
|
@@ -779,6 +780,75 @@ class Meta:
|
779 | 780 | assert serializer.is_valid()
|
780 | 781 |
|
781 | 782 |
|
| 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 | + |
782 | 852 | # Tests for `UniqueForDateValidator`
|
783 | 853 | # ----------------------------------
|
784 | 854 |
|
|
0 commit comments