[Django] #36580: Model validation of constraints fails if condition's Q object references ForeignObject

15 views
Skip to first unread message

Django

unread,
Aug 28, 2025, 6:11:37 PM (7 days ago) Aug 28
to django-...@googlegroups.com
#36580: Model validation of constraints fails if condition's Q object references
ForeignObject
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Type: Bug
Status: new | Component: Database
| layer (models, ORM)
Version: dev | Severity: Release
| blocker
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Similar to #36433, just for `ForeignObject` instead of `ForeignKey`.

With this adjusted test model and corresponding adjustment to unrelated
test, `test_full_clean_update` passes on stable/5.2.x (the constraint is
purposefully not very imaginative, can polish in PR review):
{{{#!diff
diff --git a/tests/composite_pk/models/tenant.py
b/tests/composite_pk/models/tenant.py
index 65eb0feae8..954a5519f8 100644
--- a/tests/composite_pk/models/tenant.py
+++ b/tests/composite_pk/models/tenant.py
@@ -48,6 +48,14 @@ class Comment(models.Model):
text = models.TextField(default="", blank=True)
integer = models.IntegerField(default=0)

+ class Meta:
+ constraints = [
+ models.CheckConstraint(
+ condition=models.Q(user__isnull=False),
+ name="user_not_null",
+ ),
+ ]
+

class Post(models.Model):
pk = models.CompositePrimaryKey("tenant_id", "id")
diff --git a/tests/composite_pk/tests.py b/tests/composite_pk/tests.py
index c4a8e6ca8c..cade405dee 100644
--- a/tests/composite_pk/tests.py
+++ b/tests/composite_pk/tests.py
@@ -205,12 +205,17 @@ class CompositePKTests(TestCase):
self.assertEqual(user.email, self.user.email)

def test_select_related(self):
- Comment.objects.create(tenant=self.tenant, id=2)
+ user2 = User.objects.create(
+ tenant=self.tenant,
+ id=2,
+ email="user...@example.com",
+ )
+ Comment.objects.create(tenant=self.tenant, id=2, user=user2)
with self.assertNumQueries(1):
comments =
list(Comment.objects.select_related("user").order_by("pk"))
self.assertEqual(len(comments), 2)
self.assertEqual(comments[0].user, self.user)
- self.assertIsNone(comments[1].user)
+ self.assertEqual(comments[1].user, user2)

def test_model_forms(self):
fields = ["tenant", "id", "user_id", "text", "integer"]
}}}

... but fails on main:
{{{#!py
======================================================================
ERROR: test_full_clean_update
(composite_pk.test_models.CompositePKModelsTests.test_full_clean_update)
----------------------------------------------------------------------
Traceback (most recent call last):
File
"/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/unittest/case.py",
line 58, in testPartExecutor
yield
File
"/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/unittest/case.py",
line 651, in run
self._callTestMethod(testMethod)

File
"/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/unittest/case.py",
line 606, in _callTestMethod
if method() is not None:
^^^^^^^^^^^^^^^
File "/Users/jwalls/django/tests/composite_pk/test_models.py", line 123,
in test_full_clean_update
self.comment_1.full_clean()
^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/base.py", line 1638, in
full_clean
self.validate_constraints(exclude=exclude)
^^^^^^^
File "/Users/jwalls/django/django/db/models/base.py", line 1586, in
validate_constraints
constraint.validate(model_class, self, exclude=exclude, using=using)
^^^
File "/Users/jwalls/django/django/db/models/constraints.py", line 212,
in validate
if not Q(self.condition).check(against, using=using):
^^^^^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/query_utils.py", line 176,
in check
query.add_q(Q(Coalesce(self, True, output_field=BooleanField())))
^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/sql/query.py", line 1670, in
add_q
clause, _ = self._add_q(q_object, can_reuse)
^^^^^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/sql/query.py", line 1702, in
_add_q
child_clause, needed_inner = self.build_filter(
^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/sql/query.py", line 1541, in
build_filter
condition = filter_expr.resolve_expression(
^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/expressions.py", line 301,
in resolve_expression
expr.resolve_expression(query, allow_joins, reuse, summarize,
for_save)
^^^^^^^
File "/Users/jwalls/django/django/db/models/query_utils.py", line 91, in
resolve_expression
clause, joins = query._add_q(
^^^^^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/sql/query.py", line 1702, in
_add_q
child_clause, needed_inner = self.build_filter(
^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/sql/query.py", line 1527, in
build_filter
return self._add_q(
^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/sql/query.py", line 1702, in
_add_q
child_clause, needed_inner = self.build_filter(
^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/sql/query.py", line 1550, in
build_filter
lookups, parts, reffed_expression = self.solve_lookup_type(arg,
summarize)
^^^^^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/sql/query.py", line 1357, in
solve_lookup_type
_, field, _, lookup_parts = self.names_to_path(lookup_splitted,
self.get_meta())
^^^^^^^^^^^^^^^
File "/Users/jwalls/django/django/db/models/sql/query.py", line 1830, in
names_to_path
raise FieldError(
^^^
django.core.exceptions.FieldError: Cannot resolve keyword 'user' into
field. Choices are: _check

----------------------------------------------------------------------
Ran 178 tests in 1.224s
}}}

---

There is a prior comment in ticket:36433#comment:1 about improving the
error message.
--
Ticket URL: <https://code.djangoproject.com/ticket/36580>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Aug 29, 2025, 4:48:47 AM (7 days ago) Aug 29
to django-...@googlegroups.com
#36580: Model validation of constraints fails if condition's Q object references
ForeignObject
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner:
| JaeHyuckSa
Type: Bug | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by JaeHyuckSa):

* owner: (none) => JaeHyuckSa
* status: new => assigned

--
Ticket URL: <https://code.djangoproject.com/ticket/36580#comment:1>

Django

unread,
Aug 29, 2025, 10:05:39 AM (7 days ago) Aug 29
to django-...@googlegroups.com
#36580: Model validation of constraints fails if condition's Q object references
ForeignObject
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner:
| JaeHyuckSa
Type: Bug | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Sarah Boyce):

* stage: Unreviewed => Accepted

--
Ticket URL: <https://code.djangoproject.com/ticket/36580#comment:2>

Django

unread,
Aug 30, 2025, 7:10:37 AM (6 days ago) Aug 30
to django-...@googlegroups.com
#36580: Model validation of constraints fails if condition's Q object references
ForeignObject
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner:
| JaeHyuckSa
Type: Bug | Status: assigned
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by JaeHyuckSa):

* has_patch: 0 => 1

--
Ticket URL: <https://code.djangoproject.com/ticket/36580#comment:3>

Django

unread,
Aug 30, 2025, 7:33:33 AM (6 days ago) Aug 30
to django-...@googlegroups.com
#36580: Model validation of constraints fails if condition's Q object references
ForeignObject
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner:
| JaeHyuckSa
Type: Bug | Status: closed
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution: needsinfo
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* resolution: => needsinfo
* status: assigned => closed

Comment:

I neglected to check a test project, there's a system check preventing you
from getting into this situation:

{{{
ERRORS:
models.OrderLineItem: (models.E012) 'constraints' refers to the
nonexistent field 'user'.
}}}

So this needs a more realistic test case to find out if there's a usage of
`Q()` supported on 5.2 that is actually breaking here.
--
Ticket URL: <https://code.djangoproject.com/ticket/36580#comment:4>

Django

unread,
Aug 30, 2025, 7:53:17 AM (6 days ago) Aug 30
to django-...@googlegroups.com
#36580: Model validation of constraints fails if condition's Q object references
ForeignObject
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner:
| JaeHyuckSa
Type: Bug | Status: closed
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution: needsinfo
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by JaeHyuckSa):

Replying to [comment:4 Jacob Walls]:
> I neglected to check a test project, there's a system check preventing
you from getting into this situation that errors on migrate:
>
> {{{
> ERRORS:
> models.OrderLineItem: (models.E012) 'constraints' refers to the
nonexistent field 'user'.
> }}}
>
> So this needs a more realistic test case to find out if there's a usage
of `Q()` supported on 5.2 that is actually breaking here.

Hi Jacob

Is there a way to run the system checks inside the Django source
repository rather than in my own project?
--
Ticket URL: <https://code.djangoproject.com/ticket/36580#comment:5>

Django

unread,
Aug 30, 2025, 7:55:46 AM (6 days ago) Aug 30
to django-...@googlegroups.com
#36580: Model validation of constraints fails if condition's Q object references
ForeignObject
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner:
| JaeHyuckSa
Type: Bug | Status: new
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* resolution: needsinfo =>
* status: closed => new

Comment:

Reopening, my constraint didn't match my models. Sorry for the noise!

> Is there a way to run the system checks inside the Django source
repository rather than in my own project?

I'm not sure we run system checks on test models. Not super relevant to
this ticket, as I was just totally wrong in this case, but I have noticed
it when working in the test suite that test models might not be 100%
valid.
--
Ticket URL: <https://code.djangoproject.com/ticket/36580#comment:6>

Django

unread,
Aug 30, 2025, 8:04:50 AM (6 days ago) Aug 30
to django-...@googlegroups.com
#36580: Model validation of constraints fails if condition's Q object references
ForeignObject
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner:
| JaeHyuckSa
Type: Bug | Status: new
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by JaeHyuckSa):

Replying to [comment:6 Jacob Walls]:
> Reopening, my constraint didn't match my models. Sorry for the noise!
>
> > Is there a way to run the system checks inside the Django source
repository rather than in my own project?
>
> I'm not sure we run system checks on test models. Not super relevant to
this ticket, as I was just totally wrong in this case, but I have noticed
it when working in the test suite that test models might not be 100%
valid.

I wasn’t aware of that. I’ll keep it in mind in future tests. Thank you
for your response.
--
Ticket URL: <https://code.djangoproject.com/ticket/36580#comment:7>

Django

unread,
Sep 2, 2025, 10:25:23 AM (3 days ago) Sep 2
to django-...@googlegroups.com
#36580: Model validation of constraints fails if condition's Q object references
ForeignObject
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner:
| JaeHyuckSa
Type: Bug | Status: new
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* needs_better_patch: 0 => 1

Comment:

[https://github.com/django/django/pull/19798 PR]
--
Ticket URL: <https://code.djangoproject.com/ticket/36580#comment:8>

Django

unread,
Sep 2, 2025, 1:40:17 PM (3 days ago) Sep 2
to django-...@googlegroups.com
#36580: Model validation of constraints fails if condition's Q object references
ForeignObject
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner:
| JaeHyuckSa
Type: Bug | Status: new
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by JaeHyuckSa):

* needs_better_patch: 1 => 0

--
Ticket URL: <https://code.djangoproject.com/ticket/36580#comment:9>

Django

unread,
Sep 2, 2025, 2:36:59 PM (3 days ago) Sep 2
to django-...@googlegroups.com
#36580: Model validation of constraints fails if condition's Q object references
ForeignObject
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Owner:
| JaeHyuckSa
Type: Bug | Status: new
Component: Database layer | Version: dev
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* needs_better_patch: 0 => 1

--
Ticket URL: <https://code.djangoproject.com/ticket/36580#comment:10>
Reply all
Reply to author
Forward
0 new messages