1
0
mirror of https://github.com/django/django.git synced 2024-12-22 17:16:24 +00:00

Fixed #21760 -- prefetch_related used an inefficient query for reverse FK.

Regression introduced by commit 9777442. Refs #21410.
This commit is contained in:
valtron 2014-04-11 19:27:34 -06:00 committed by Loic Bistuer
parent 3417ba0309
commit d3b71b976d
4 changed files with 26 additions and 1 deletions

View File

@ -635,6 +635,7 @@ answer newbie questions, and generally made Django that much better:
Justine Tunney <jtunney@lobstertech.com> Justine Tunney <jtunney@lobstertech.com>
Maxime Turcotte <maxocub@riseup.net> Maxime Turcotte <maxocub@riseup.net>
Amit Upadhyay <http://www.amitu.com/blog/> Amit Upadhyay <http://www.amitu.com/blog/>
valtron
Adam Vandenberg Adam Vandenberg
Geert Vanderkelen Geert Vanderkelen
Vasil Vangelovski Vasil Vangelovski

View File

@ -521,7 +521,9 @@ class ReverseSingleRelatedObjectDescriptor(object):
# composite fields. In the meantime we take this practical approach to # composite fields. In the meantime we take this practical approach to
# solve a regression on 1.6 when the reverse manager in hidden # solve a regression on 1.6 when the reverse manager in hidden
# (related_name ends with a '+'). Refs #21410. # (related_name ends with a '+'). Refs #21410.
if self.field.rel.is_hidden(): # The check for len(...) == 1 is a special case that allows the query
# to be join-less and smaller. Refs #21760.
if self.field.rel.is_hidden() or len(self.field.foreign_related_fields) == 1:
query = {'%s__in' % related_field.name: set(instance_attr(inst)[0] for inst in instances)} query = {'%s__in' % related_field.name: set(instance_attr(inst)[0] for inst in instances)}
else: else:
query = {'%s__in' % self.field.related_query_name(): instances} query = {'%s__in' % self.field.related_query_name(): instances}

View File

@ -67,5 +67,9 @@ Other bugfixes and changes
* Fixed :djadmin:`changepassword` on Windows * Fixed :djadmin:`changepassword` on Windows
(`#22364 <https://code.djangoproject.com/ticket/22364>`_). (`#22364 <https://code.djangoproject.com/ticket/22364>`_).
* Fixed regression in ``prefetch_related`` that caused the related objects
query to include an unnecessary join
(`#21760 <https://code.djangoproject.com/ticket/21760>`_).
Additionally, Django's vendored version of six, :mod:`django.utils.six` has been Additionally, Django's vendored version of six, :mod:`django.utils.six` has been
upgraded to the latest release (1.6.1). upgraded to the latest release (1.6.1).

View File

@ -4,8 +4,10 @@ from django.core.exceptions import ObjectDoesNotExist
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db import connection from django.db import connection
from django.db.models import Prefetch from django.db.models import Prefetch
from django.db.models.query import get_prefetcher
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
from django.utils import six from django.utils import six
from django.utils.encoding import force_text
from .models import (Author, Book, Reader, Qualification, Teacher, Department, from .models import (Author, Book, Reader, Qualification, Teacher, Department,
TaggedItem, Bookmark, AuthorAddress, FavoriteAuthors, AuthorWithAge, TaggedItem, Bookmark, AuthorAddress, FavoriteAuthors, AuthorWithAge,
@ -1055,3 +1057,19 @@ class Ticket21410Tests(TestCase):
def test_bug(self): def test_bug(self):
list(Author2.objects.prefetch_related('first_book', 'favorite_books')) list(Author2.objects.prefetch_related('first_book', 'favorite_books'))
class Ticket21760Tests(TestCase):
def setUp(self):
self.rooms = []
for _ in range(3):
house = House.objects.create()
for _ in range(3):
self.rooms.append(Room.objects.create(house = house))
#@override_settings(DEBUG=True)
def test_bug(self):
prefetcher = get_prefetcher(self.rooms[0], 'house')[0]
queryset = prefetcher.get_prefetch_queryset(list(Room.objects.all()))[0]
self.assertNotIn(' JOIN ', force_text(queryset.query))