diff options
| author | valtron <valtron2000@gmail.com> | 2014-04-11 19:27:34 -0600 |
|---|---|---|
| committer | Loic Bistuer <loic.bistuer@gmail.com> | 2014-04-13 01:06:03 +0700 |
| commit | 1252b77824639fba398cf70586bdd75c42f86fdf (patch) | |
| tree | 31e7642799ccfc2c5082b9fa22242d0fa38a95f3 | |
| parent | a3570798929337baeba237c7e7eec35d9f2c18c4 (diff) | |
[1.6.x] Fixed #21760 -- prefetch_related used an inefficient query for reverse FK.
Regression introduced by commit 9777442. Refs #21410.
Conflicts:
tests/prefetch_related/tests.py
Backport of d3b71b976d from master
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | django/db/models/fields/related.py | 4 | ||||
| -rw-r--r-- | docs/releases/1.6.3.txt | 4 | ||||
| -rw-r--r-- | tests/prefetch_related/tests.py | 17 |
4 files changed, 25 insertions, 1 deletions
@@ -599,6 +599,7 @@ answer newbie questions, and generally made Django that much better: David Tulig <david.tulig@gmail.com> Justine Tunney <jtunney@lobstertech.com> Amit Upadhyay <http://www.amitu.com/blog/> + valtron Adam Vandenberg Geert Vanderkelen Vasil Vangelovski diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index d50c72d66c..a4bc374d01 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -279,7 +279,9 @@ class ReverseSingleRelatedObjectDescriptor(six.with_metaclass(RenameRelatedObjec # composite fields. In the meantime we take this practical approach to # solve a regression on 1.6 when the reverse manager in hidden # (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)} else: query = {'%s__in' % self.field.related_query_name(): instances} diff --git a/docs/releases/1.6.3.txt b/docs/releases/1.6.3.txt index 538c67e5dc..c6adbcf09c 100644 --- a/docs/releases/1.6.3.txt +++ b/docs/releases/1.6.3.txt @@ -67,5 +67,9 @@ Other bugfixes and changes * Fixed :djadmin:`changepassword` on Windows (`#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 upgraded to the latest release (1.6.1). diff --git a/tests/prefetch_related/tests.py b/tests/prefetch_related/tests.py index 384457aba4..90a27f818c 100644 --- a/tests/prefetch_related/tests.py +++ b/tests/prefetch_related/tests.py @@ -2,9 +2,11 @@ from __future__ import absolute_import, unicode_literals from django.contrib.contenttypes.models import ContentType from django.db import connection +from django.db.models.query import get_prefetcher from django.test import TestCase from django.test.utils import override_settings from django.utils import six +from django.utils.encoding import force_text from .models import (Author, Book, Reader, Qualification, Teacher, Department, TaggedItem, Bookmark, AuthorAddress, FavoriteAuthors, AuthorWithAge, @@ -677,3 +679,18 @@ class Ticket21410Tests(TestCase): def test_bug(self): 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)) + + 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)) |
