From 51c9bb7cd16081133af4f0ab6d06572660309730 Mon Sep 17 00:00:00 2001 From: Xavier Fernandez Date: Wed, 22 Feb 2023 21:04:05 +0100 Subject: [PATCH] Refs #33829 -- Added violation_error_message to constraints' __repr__(). --- django/contrib/postgres/constraints.py | 8 +++++++- django/db/models/constraints.py | 16 +++++++++++++-- tests/constraints/tests.py | 26 ++++++++++++++++++++++++ tests/postgres_tests/test_constraints.py | 11 ++++++++++ 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/django/contrib/postgres/constraints.py b/django/contrib/postgres/constraints.py index 30ef7602a50..ad3a5f61f55 100644 --- a/django/contrib/postgres/constraints.py +++ b/django/contrib/postgres/constraints.py @@ -154,7 +154,7 @@ class ExclusionConstraint(BaseConstraint): return super().__eq__(other) def __repr__(self): - return "<%s: index_type=%s expressions=%s name=%s%s%s%s>" % ( + return "<%s: index_type=%s expressions=%s name=%s%s%s%s%s>" % ( self.__class__.__qualname__, repr(self.index_type), repr(self.expressions), @@ -162,6 +162,12 @@ class ExclusionConstraint(BaseConstraint): "" if self.condition is None else " condition=%s" % self.condition, "" if self.deferrable is None else " deferrable=%r" % self.deferrable, "" if not self.include else " include=%s" % repr(self.include), + ( + "" + if self.violation_error_message is None + or self.violation_error_message == self.default_violation_error_message + else " violation_error_message=%r" % self.violation_error_message + ), ) def validate(self, model, instance, exclude=None, using=DEFAULT_DB_ALIAS): diff --git a/django/db/models/constraints.py b/django/db/models/constraints.py index 237b1860507..075ecee1be7 100644 --- a/django/db/models/constraints.py +++ b/django/db/models/constraints.py @@ -117,10 +117,16 @@ class CheckConstraint(BaseConstraint): pass def __repr__(self): - return "<%s: check=%s name=%s>" % ( + return "<%s: check=%s name=%s%s>" % ( self.__class__.__qualname__, self.check, repr(self.name), + ( + "" + if self.violation_error_message is None + or self.violation_error_message == self.default_violation_error_message + else " violation_error_message=%r" % self.violation_error_message + ), ) def __eq__(self, other): @@ -287,7 +293,7 @@ class UniqueConstraint(BaseConstraint): ) def __repr__(self): - return "<%s:%s%s%s%s%s%s%s>" % ( + return "<%s:%s%s%s%s%s%s%s%s>" % ( self.__class__.__qualname__, "" if not self.fields else " fields=%s" % repr(self.fields), "" if not self.expressions else " expressions=%s" % repr(self.expressions), @@ -296,6 +302,12 @@ class UniqueConstraint(BaseConstraint): "" if self.deferrable is None else " deferrable=%r" % self.deferrable, "" if not self.include else " include=%s" % repr(self.include), "" if not self.opclasses else " opclasses=%s" % repr(self.opclasses), + ( + "" + if self.violation_error_message is None + or self.violation_error_message == self.default_violation_error_message + else " violation_error_message=%r" % self.violation_error_message + ), ) def __eq__(self, other): diff --git a/tests/constraints/tests.py b/tests/constraints/tests.py index e486a35b7ae..b45dc6499a3 100644 --- a/tests/constraints/tests.py +++ b/tests/constraints/tests.py @@ -160,6 +160,18 @@ class CheckConstraintTests(TestCase): "name='price_gt_discounted_price'>", ) + def test_repr_with_violation_error_message(self): + constraint = models.CheckConstraint( + check=models.Q(price__lt=1), + name="price_lt_one", + violation_error_message="More than 1", + ) + self.assertEqual( + repr(constraint), + "", + ) + def test_invalid_check_types(self): msg = "CheckConstraint.check must be a Q instance or boolean expression." with self.assertRaisesMessage(TypeError, msg): @@ -486,6 +498,20 @@ class UniqueConstraintTests(TestCase): "name='book_func_uq'>", ) + def test_repr_with_violation_error_message(self): + constraint = models.UniqueConstraint( + models.F("baz__lower"), + name="unique_lower_baz", + violation_error_message="BAZ", + ) + self.assertEqual( + repr(constraint), + ( + "" + ), + ) + def test_deconstruction(self): fields = ["foo", "bar"] name = "unique_fields" diff --git a/tests/postgres_tests/test_constraints.py b/tests/postgres_tests/test_constraints.py index e601f347eb6..a5248e14916 100644 --- a/tests/postgres_tests/test_constraints.py +++ b/tests/postgres_tests/test_constraints.py @@ -386,6 +386,17 @@ class ExclusionConstraintTests(PostgreSQLTestCase): "(OpClass(F(datespan), name=range_ops), '-|-')] " "name='exclude_overlapping'>", ) + constraint = ExclusionConstraint( + name="exclude_overlapping", + expressions=[(F("datespan"), RangeOperators.ADJACENT_TO)], + violation_error_message="Overlapping must be excluded", + ) + self.assertEqual( + repr(constraint), + "", + ) def test_eq(self): constraint_1 = ExclusionConstraint(