from django.db import models
from django.db.models.constraints import CheckConstraint
from django.db.models import F, Q
# model with self FK
class Structure(models.Model):
upper_structure = models.ForeignKey(
"self",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="structures",
)
class Meta:
constraints = [
# un poste ne peut pas etre lui-meme sont poste superieur
CheckConstraint(
check=~Q(pk=F("upper_structure__pk")),
name="%(app_label)s_%(class)s_upper_structure_not_equals_self",
)
]
# check the issue here
s = Structure()
s.full_clean()
Expected behavior calling full_clean() shoul not trigger the error
#Here is the stack trace
File "/home/plexuserp/venv/lib/python3.11/site-packages/django/db/models/base.py", line 1491, in full_clean
self.validate_constraints(exclude=exclude)
File "/home/plexuserp/venv/lib/python3.11/site-packages/django/db/models/base.py", line 1442, in validate_constraints
constraint.validate(model_class, self, exclude=exclude, using=using)
File "/home/plexuserp/venv/lib/python3.11/site-packages/django/db/models/constraints.py", line 92, in validate
if not Q(self.check).check(against, using=using):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/plexuserp/venv/lib/python3.11/site-packages/django/db/models/query_utils.py", line 134, in check
query.add_q(self)
File "/home/plexuserp/venv/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1532, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/plexuserp/venv/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1562, in _add_q
child_clause, needed_inner = self.build_filter(
^^^^^^^^^^^^^^^^^^
File "/home/plexuserp/venv/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1388, in build_filter
return self._add_q(
^^^^^^^^^^^^
File "/home/plexuserp/venv/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1562, in _add_q
child_clause, needed_inner = self.build_filter(
^^^^^^^^^^^^^^^^^^
File "/home/plexuserp/venv/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1407, in build_filter
lookups, parts, reffed_expression = self.solve_lookup_type(arg)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/plexuserp/venv/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1217, in solve_lookup_type
_, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/plexuserp/venv/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1656, in names_to_path
name = opts.pk.name
^^^^^^^
AttributeError: 'NoneType' object has no attribute 'pk'
Constraints that refers to the joined field are not allowed:
However, it raises the same error for
check=~Q(pk=F("upper_structure_id"))
which is allowed.