Fixed #30771 -- Fixed exact lookup against queries with selected columns.

Use pre-existing select fields (and thereby GROUP BY fields) from
subquery if they were specified, instead of always defaulting to pk.

Thanks Aur Saraf for the report and Simon Charette for guidance.
This commit is contained in:
James Timmins 2019-09-19 19:20:40 -07:00 committed by Mariusz Felisiak
parent 3346b78a8a
commit 0719edcd5f
3 changed files with 17 additions and 3 deletions

View File

@ -384,6 +384,7 @@ answer newbie questions, and generally made Django that much better:
James Bennett <james@b-list.org> James Bennett <james@b-list.org>
James Murty James Murty
James Tauber <jtauber@jtauber.com> James Tauber <jtauber@jtauber.com>
James Timmins <jameshtimmins@gmail.com>
James Wheare <django@sparemint.com> James Wheare <django@sparemint.com>
Jannis Leidel <jannis@leidel.info> Jannis Leidel <jannis@leidel.info>
Janos Guljas Janos Guljas

View File

@ -262,9 +262,9 @@ class Exact(FieldGetDbPrepValueMixin, BuiltinLookup):
from django.db.models.sql.query import Query from django.db.models.sql.query import Query
if isinstance(self.rhs, Query): if isinstance(self.rhs, Query):
if self.rhs.has_limit_one(): if self.rhs.has_limit_one():
# The subquery must select only the pk. if not self.rhs.has_select_fields:
self.rhs.clear_select_clause() self.rhs.clear_select_clause()
self.rhs.add_fields(['pk']) self.rhs.add_fields(['pk'])
else: else:
raise ValueError( raise ValueError(
'The QuerySet value for an exact lookup must be limited to ' 'The QuerySet value for an exact lookup must be limited to '

View File

@ -5,6 +5,7 @@ from operator import attrgetter
from django.core.exceptions import FieldError from django.core.exceptions import FieldError
from django.db import connection from django.db import connection
from django.db.models import Max
from django.db.models.expressions import Exists, OuterRef from django.db.models.expressions import Exists, OuterRef
from django.db.models.functions import Substr from django.db.models.functions import Substr
from django.test import TestCase, skipUnlessDBFeature from django.test import TestCase, skipUnlessDBFeature
@ -956,3 +957,15 @@ class LookupTests(TestCase):
), ),
) )
self.assertEqual(qs.get(has_author_alias_match=True), tag) self.assertEqual(qs.get(has_author_alias_match=True), tag)
def test_exact_query_rhs_with_selected_columns(self):
newest_author = Author.objects.create(name='Author 2')
authors_max_ids = Author.objects.filter(
name='Author 2',
).values(
'name',
).annotate(
max_id=Max('id'),
).values('max_id')
authors = Author.objects.filter(id=authors_max_ids[:1])
self.assertEqual(authors.get(), newest_author)