summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2024-07-13 22:09:50 -0400
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2024-07-17 12:55:36 +0200
commita2791f5ea2cb3bfa5b386083002461be40708297 (patch)
tree3c38fbaa1cd61d190a6e5d39bb789c65e0e64ded
parentdf7ebb8b0205273f71c60c33a5de0b680d6a3849 (diff)
[5.1.x] Refs #30581 -- Made unattached UniqueConstraint(fields) validation testable.
The logic allowing UniqueConstraint(fields).validate to preserve backward compatiblity with Model.unique_error_message failed to account for cases where the constraint might not be attached to a model which is a common pattern during testing. This changes allows for arbitrary UniqueConstraint(fields) to be tested in isolation without requiring actual models backing them up. Co-authored-by: Mark G <mark.gensler@protonmail.com> Backport of 13922580cccfb9ab2922ff4943dd39da56dfbd8c from main.
-rw-r--r--django/db/models/constraints.py19
-rw-r--r--tests/constraints/tests.py9
2 files changed, 16 insertions, 12 deletions
diff --git a/django/db/models/constraints.py b/django/db/models/constraints.py
index 3e6c5205c6..9bb407274c 100644
--- a/django/db/models/constraints.py
+++ b/django/db/models/constraints.py
@@ -653,19 +653,16 @@ class UniqueConstraint(BaseConstraint):
queryset = queryset.exclude(pk=model_class_pk)
if not self.condition:
if queryset.exists():
- if self.expressions:
+ if self.fields:
+ # When fields are defined, use the unique_error_message() for
+ # backward compatibility.
raise ValidationError(
- self.get_violation_error_message(),
- code=self.violation_error_code,
+ instance.unique_error_message(model, self.fields),
)
- # When fields are defined, use the unique_error_message() for
- # backward compatibility.
- for model, constraints in instance.get_constraints():
- for constraint in constraints:
- if constraint is self:
- raise ValidationError(
- instance.unique_error_message(model, self.fields),
- )
+ raise ValidationError(
+ self.get_violation_error_message(),
+ code=self.violation_error_code,
+ )
else:
against = instance._get_field_value_map(meta=model._meta, exclude=exclude)
try:
diff --git a/tests/constraints/tests.py b/tests/constraints/tests.py
index 86efaa79e7..8b7599adc1 100644
--- a/tests/constraints/tests.py
+++ b/tests/constraints/tests.py
@@ -896,6 +896,13 @@ class UniqueConstraintTests(TestCase):
ChildUniqueConstraintProduct(name=self.p1.name, color=self.p1.color),
)
+ def test_validate_fields_unattached(self):
+ Product.objects.create(price=42)
+ constraint = models.UniqueConstraint(fields=["price"], name="uniq_prices")
+ msg = "Product with this Price already exists."
+ with self.assertRaisesMessage(ValidationError, msg):
+ constraint.validate(Product, Product(price=42))
+
@skipUnlessDBFeature("supports_partial_indexes")
def test_validate_condition(self):
p1 = UniqueConstraintConditionProduct.objects.create(name="p1")
@@ -921,7 +928,7 @@ class UniqueConstraintTests(TestCase):
)
@skipUnlessDBFeature("supports_partial_indexes")
- def test_validate_conditon_custom_error(self):
+ def test_validate_condition_custom_error(self):
p1 = UniqueConstraintConditionProduct.objects.create(name="p1")
constraint = models.UniqueConstraint(
fields=["name"],