Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #21760 -- prefetch_related used an inefficient query for revers…

…e FK.

Regression introduced by commit 9777442. Refs #21410.
  • Loading branch information...
commit d3b71b976dee4b02908235b8007db254a9795268 1 parent 3417ba0
@valtron valtron authored loic committed
View
1  AUTHORS
@@ -635,6 +635,7 @@ answer newbie questions, and generally made Django that much better:
Justine Tunney <jtunney@lobstertech.com>
Maxime Turcotte <maxocub@riseup.net>
Amit Upadhyay <http://www.amitu.com/blog/>
+ valtron
Adam Vandenberg
Geert Vanderkelen
Vasil Vangelovski
View
4 django/db/models/fields/related.py
@@ -521,7 +521,9 @@ def get_prefetch_queryset(self, instances, queryset=None):
# 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}
View
4 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).
View
18 tests/prefetch_related/tests.py
@@ -4,8 +4,10 @@
from django.contrib.contenttypes.models import ContentType
from django.db import connection
from django.db.models import Prefetch
+from django.db.models.query import get_prefetcher
from django.test import TestCase, 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,
@@ -1055,3 +1057,19 @@ def setUp(self):
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))
+
+ #@override_settings(DEBUG=True)
@claudep Collaborator
claudep added a note

I would not have left this commented line. Or add another comment to comment the reason :-)

@loic Collaborator
loic added a note

Thanks, fixed.

It was a vestige from a previous test attempt that extracted the query from db.connections.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ 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))
Please sign in to comment.
Something went wrong with that request. Please try again.