diff --git a/django/db/models/base.py b/django/db/models/base.py index 3e9b847b37a..5c0a9c430f3 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 9853919482e..6a9348af665 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 f6571084b05..55397449d9a 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