8000 Fixed #36210 -- Allowed Subquery usage in futher lookups against comp… · django/django@82bdc88 · GitHub
[go: up one dir, main page]

Skip to content

Commit 82bdc88

Browse files
Fixed #36210 -- Allowed Subquery usage in futher lookups against composite pks.
Follow-up to 8561100. co-authored-by: Simon Charette <charette.s@gmail.com>
1 parent 926e2a2 commit 82bdc88

File tree

3 files changed

+25
-1
lines changed

3 files changed

+25
-1
lines changed

django/db/models/expressions.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,6 +1756,7 @@ def __init__(self, queryset, output_field=None, **extra):
17561756
# Allow the usage of both QuerySet and sql.Query objects.
17571757
self.query = getattr(queryset, "query", queryset).clone()
17581758
self.query.subquery = True
1759+
self.template = extra.pop("template", self.template)
17591760
self.extra = extra
17601761
super().__init__(output_field)
17611762

@@ -1768,6 +1769,14 @@ def set_source_expressions(self, exprs):
17681769
def _resolve_output_field(self):
17691770
return self.query.output_field
17701771

1772+
def resolve_expression(self, *args, **kwargs):
1773+
resolved = super().resolve_expression(*args, **kwargs)
1774+
if self.template == Subquery.template:
1775+
# Subquery is an unnecessary shim for a resolved query as it
1776+
# complexifies the lookup's right-hand-side introspection.
1777+
return resolved.query
1778+
return resolved
1779+
17711780
def copy(self):
17721781
clone = super().copy()
17731782
clone.query = clone.query.clone()

django/db/models/sql/query.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ class Query(BaseExpression):
235235

236236
filter_is_sticky = False
237237
subquery = False
238+
contains_subquery = True
238239

239240
# SQL-related attributes.
240241
# Select and related select clauses are expressions to use in the SELECT
@@ -1226,7 +1227,7 @@ def add_annotation(self, annotation, alias, select=True):
12261227

12271228
@property
12281229
def _subquery_fields_len(self):
1229-
if self.has_select_fields:
1230+
if self.has_select_fields and tuple(self.selected) != ("pk",):
12301231
return len(self.selected)
12311232
return len(self.model._meta.pk_fields)
12321233

tests/composite_pk/test_filter.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,20 @@ def test_outer_ref_pk(self):
476476
queryset = Comment.objects.filter(**{f"id{lookup}": subquery})
477477
self.assertEqual(queryset.count(), expected_count)
478478

479+
def test_outer_ref_pk_select_pk(self):
480+
subquery = Subquery(User.objects.filter(pk=OuterRef("pk")).values("pk")[:1])
481+
tests = [
482+
("", 2),
483+
("__gt", 0),
484+
("__gte", 2),
485+
("__lt", 0),
486+
("__lte", 2),
487+
]
488+
for lookup, expected_count in tests:
489+
with self.subTest(f"pk{lookup}"):
490+
qs = Comment.objects.filter(**{f"pk{lookup}": subquery})
491+
self.assertEqual(qs.count(), expected_count)
492+
479493
def test_unsupported_rhs(self):
480494
pk = Exact(F("tenant_id"), 1)
481495
msg = (

0 commit comments

Comments
 (0)
0