summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco Panico <francesco.panico@fiscozen.it>2023-08-10 14:08:11 +0000
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-08-11 08:51:29 +0200
commit1506f498fe42b65730ece809300c2c0963e38c5a (patch)
tree8c83a06a590e73a4ae88f8cdc43bfa8f1c8f2edc
parent9946f0b0d9356b55e819f861b31615fa5b548f99 (diff)
Fixed #34743 -- Fixed Meta.constraints validation crash when using pk.
Thanks Nwawel A Iroume for the report.
-rw-r--r--django/db/models/base.py5
-rw-r--r--django/db/models/sql/query.py2
-rw-r--r--tests/constraints/tests.py13
3 files changed, 18 insertions, 2 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 3e9b847b37..5c0a9c430f 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -1235,11 +1235,14 @@ class Model(AltersData, metaclass=ModelBase):
if exclude is None:
exclude = set()
meta = meta or self._meta
- return {
+ field_map = {
field.name: Value(getattr(self, field.attname), field)
for field in meta.local_concrete_fields
if field.name not in exclude
}
+ if "pk" not in exclude:
+ field_map["pk"] = Value(self.pk, meta.pk)
+ return field_map
def prepare_database_save(self, field):
if self.pk is None:
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 9853919482..6a9348af66 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -1670,7 +1670,7 @@ class Query(BaseExpression):
path, names_with_path = [], []
for pos, name in enumerate(names):
cur_names_with_path = (name, [])
- if name == "pk":
+ if name == "pk" and opts is not None:
name = opts.pk.name
field = None
diff --git a/tests/constraints/tests.py b/tests/constraints/tests.py
index f6571084b0..55397449d9 100644
--- a/tests/constraints/tests.py
+++ b/tests/constraints/tests.py
@@ -352,6 +352,19 @@ class CheckConstraintTests(TestCase):
is_not_null_constraint.validate(JSONFieldModel, JSONFieldModel(data=None))
is_not_null_constraint.validate(JSONFieldModel, JSONFieldModel(data={}))
+ def test_validate_pk_field(self):
+ constraint_with_pk = models.CheckConstraint(
+ check=~models.Q(pk=models.F("age")),
+ name="pk_not_age_check",
+ )
+ constraint_with_pk.validate(ChildModel, ChildModel(pk=1, age=2))
+ msg = f"Constraint “{constraint_with_pk.name}” is violated."
+ with self.assertRaisesMessage(ValidationError, msg):
+ constraint_with_pk.validate(ChildModel, ChildModel(pk=1, age=1))
+ with self.assertRaisesMessage(ValidationError, msg):
+ constraint_with_pk.validate(ChildModel, ChildModel(id=1, age=1))
+ constraint_with_pk.validate(ChildModel, ChildModel(pk=1, age=1), exclude={"pk"})
+
class UniqueConstraintTests(TestCase):
@classmethod