Fixed #17668 - prefetch_related does not work in in_bulk

Thanks to gurets for the report, and akaariai for the initial patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17600 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Luke Plant 2012-02-28 19:34:04 +00:00
parent 4b641b78fa
commit de9942a667
3 changed files with 20 additions and 1 deletions

View File

@ -485,7 +485,7 @@ class QuerySet(object):
qs = self._clone() qs = self._clone()
qs.query.add_filter(('pk__in', id_list)) qs.query.add_filter(('pk__in', id_list))
qs.query.clear_ordering(force_empty=True) qs.query.clear_ordering(force_empty=True)
return dict([(obj._get_pk_val(), obj) for obj in qs.iterator()]) return dict([(obj._get_pk_val(), obj) for obj in qs])
def delete(self): def delete(self):
""" """

View File

@ -871,6 +871,9 @@ could be generated, which, depending on the database, might have performance
problems of its own when it comes to parsing or executing the SQL query. Always problems of its own when it comes to parsing or executing the SQL query. Always
profile for your use case! profile for your use case!
Note that if you use ``iterator()`` to run the query, ``prefetch_related()``
calls will be ignored since these two optimizations do not make sense together.
extra extra
~~~~~ ~~~~~
@ -1430,6 +1433,9 @@ performance and a significant reduction in memory.
Note that using ``iterator()`` on a ``QuerySet`` which has already been Note that using ``iterator()`` on a ``QuerySet`` which has already been
evaluated will force it to evaluate again, repeating the query. evaluated will force it to evaluate again, repeating the query.
Also, use of ``iterator()`` causes previous ``prefetch_related()`` calls to be
ignored since these two optimizations do not make sense together.
latest latest
~~~~~~ ~~~~~~

View File

@ -470,3 +470,16 @@ class NullableTest(TestCase):
for e in qs2] for e in qs2]
self.assertEqual(co_serfs, co_serfs2) self.assertEqual(co_serfs, co_serfs2)
def test_in_bulk(self):
"""
In-bulk does correctly prefetch objects by not using .iterator()
directly.
"""
boss1 = Employee.objects.create(name="Peter")
boss2 = Employee.objects.create(name="Jack")
with self.assertNumQueries(2):
# Check that prefetch is done and it does not cause any errors.
bulk = Employee.objects.prefetch_related('serfs').in_bulk([boss1.pk, boss2.pk])
for b in bulk.values():
list(b.serfs.all())