summaryrefslogtreecommitdiff
path: root/tests/model_fields/test_generatedfield.py
diff options
context:
space:
mode:
authorMark Gensler <mark.gensler@protonmail.com>2024-06-25 15:04:48 +0100
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2024-07-04 11:45:15 +0200
commit1005c2abd1ef0c156f449641e38c33e473989d37 (patch)
treedda3a6827743dcffd1bd35a63a259dde4a6c30d3 /tests/model_fields/test_generatedfield.py
parent53e674d5744faad61e52d8459c9198b2aa6f63dd (diff)
Fixed #35560 -- Made Model.full_clean() ignore GeneratedFields for constraints.
Accessing generated field values on unsaved models caused a crash when validating CheckConstraints and UniqueConstraints with expressions.
Diffstat (limited to 'tests/model_fields/test_generatedfield.py')
-rw-r--r--tests/model_fields/test_generatedfield.py45
1 files changed, 45 insertions, 0 deletions
diff --git a/tests/model_fields/test_generatedfield.py b/tests/model_fields/test_generatedfield.py
index 2fbfe3c82a..c185e19d8b 100644
--- a/tests/model_fields/test_generatedfield.py
+++ b/tests/model_fields/test_generatedfield.py
@@ -2,6 +2,7 @@ import uuid
from decimal import Decimal
from django.apps import apps
+from django.core.exceptions import ValidationError
from django.db import IntegrityError, connection
from django.db.models import (
CharField,
@@ -18,6 +19,8 @@ from django.test.utils import isolate_apps
from .models import (
Foo,
GeneratedModel,
+ GeneratedModelCheckConstraint,
+ GeneratedModelCheckConstraintVirtual,
GeneratedModelFieldWithConverters,
GeneratedModelNull,
GeneratedModelNullVirtual,
@@ -25,6 +28,8 @@ from .models import (
GeneratedModelOutputFieldDbCollationVirtual,
GeneratedModelParams,
GeneratedModelParamsVirtual,
+ GeneratedModelUniqueConstraint,
+ GeneratedModelUniqueConstraintVirtual,
GeneratedModelVirtual,
)
@@ -186,6 +191,42 @@ class GeneratedFieldTestMixin:
m = self._refresh_if_needed(m)
self.assertEqual(m.field, 3)
+ @skipUnlessDBFeature("supports_table_check_constraints")
+ def test_full_clean_with_check_constraint(self):
+ model_name = self.check_constraint_model._meta.verbose_name.capitalize()
+
+ m = self.check_constraint_model(a=2)
+ m.full_clean()
+ m.save()
+ m = self._refresh_if_needed(m)
+ self.assertEqual(m.a_squared, 4)
+
+ m = self.check_constraint_model(a=-1)
+ with self.assertRaises(ValidationError) as cm:
+ m.full_clean()
+ self.assertEqual(
+ cm.exception.message_dict,
+ {"__all__": [f"Constraint “{model_name} a > 0” is violated."]},
+ )
+
+ @skipUnlessDBFeature("supports_expression_indexes")
+ def test_full_clean_with_unique_constraint_expression(self):
+ model_name = self.unique_constraint_model._meta.verbose_name.capitalize()
+
+ m = self.unique_constraint_model(a=2)
+ m.full_clean()
+ m.save()
+ m = self._refresh_if_needed(m)
+ self.assertEqual(m.a_squared, 4)
+
+ m = self.unique_constraint_model(a=2)
+ with self.assertRaises(ValidationError) as cm:
+ m.full_clean()
+ self.assertEqual(
+ cm.exception.message_dict,
+ {"__all__": [f"Constraint “{model_name} a” is violated."]},
+ )
+
def test_create(self):
m = self.base_model.objects.create(a=1, b=2)
m = self._refresh_if_needed(m)
@@ -305,6 +346,8 @@ class GeneratedFieldTestMixin:
class StoredGeneratedFieldTests(GeneratedFieldTestMixin, TestCase):
base_model = GeneratedModel
nullable_model = GeneratedModelNull
+ check_constraint_model = GeneratedModelCheckConstraint
+ unique_constraint_model = GeneratedModelUniqueConstraint
output_field_db_collation_model = GeneratedModelOutputFieldDbCollation
params_model = GeneratedModelParams
@@ -318,5 +361,7 @@ class StoredGeneratedFieldTests(GeneratedFieldTestMixin, TestCase):
class VirtualGeneratedFieldTests(GeneratedFieldTestMixin, TestCase):
base_model = GeneratedModelVirtual
nullable_model = GeneratedModelNullVirtual
+ check_constraint_model = GeneratedModelCheckConstraintVirtual
+ unique_constraint_model = GeneratedModelUniqueConstraintVirtual
output_field_db_collation_model = GeneratedModelOutputFieldDbCollationVirtual
params_model = GeneratedModelParamsVirtual