#36050: Cannot resolve OuterRef to CompositePrimaryKey
-------------------------------------+-------------------------------------
Reporter: Jacob Walls | Type: New
| feature
Status: new | Component: Database
| layer (models, ORM)
Version: dev | Severity: Normal
Keywords: subquery | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
With CompositePrimaryKey, using `OuterRef("pk")` in a subquery raises
ValueError. Not certain if this is a release blocker or a new feature. If
it's a new feature, we might want to document that it's not currently
supported.
{{{#!diff
diff --git a/tests/composite_pk/test_filter.py
b/tests/composite_pk/test_filter.py
index 7e361c5925..c3dfc8d44b 100644
--- a/tests/composite_pk/test_filter.py
+++ b/tests/composite_pk/test_filter.py
@@ -1,3 +1,4 @@
+from django.db.models import OuterRef, Subquery
from django.test import TestCase
from .models import Comment, Tenant, User
@@ -54,6 +55,12 @@ class CompositePKFilterTests(TestCase):
with self.subTest(lookup=lookup, count=count):
self.assertEqual(User.objects.filter(**lookup).count(),
count)
+ def test_outer_ref_pk(self):
+ qs = Comment.objects.filter(
+
id__gt=Subquery(Comment.objects.filter(pk=OuterRef("pk")).values("id")[:1])
+ )
+ self.assertEqual(qs.count(), 0)
+
def test_order_comments_by_pk_asc(self):
self.assertSequenceEqual(
Comment.objects.order_by("pk"),
}}}
{{{
File "/Users/.../django/django/db/models/fields/tuple_lookups.py", line
32, in get_prep_lookup
self.check_rhs_is_tuple_or_list()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/Users/.../django/django/db/models/fields/tuple_lookups.py", line
39, in check_rhs_is_tuple_or_list
raise ValueError(
f"{self.lookup_name!r} lookup of {lhs_str} must be a tuple or a
list"
)
ValueError: 'exact' lookup of 'pk' must be a tuple or a list
}}}
----
Adjusting the guard that raises ValueError to also accept
`ResolvedOuterRef` leads to a more interesting failure:
{{{
File "/Users/.../django/django/db/models/expressions.py", line 1162, in
as_sql
val = output_field.get_db_prep_value(val, connection=connection)
File "/Users/.../django/django/db/models/fields/related.py", line 1161,
in get_db_prep_value
return self.target_field.get_db_prep_value(value, connection,
prepared)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/.../django/django/db/models/fields/__init__.py", line 2819,
in get_db_prep_value
value = self.get_prep_value(value)
File "/Users/.../django/django/db/models/fields/__init__.py", line 2129,
in get_prep_value
raise e.__class__(
"Field '%s' expected a number but got %r." % (
self.name, value),
) from e
TypeError: Field 'id' expected a number but got Col(composite_pk_comment,
composite_pk.Comment.tenant).
}}}
--
Ticket URL: <
https://code.djangoproject.com/ticket/36050>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.