Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Optimisation in prefetch_related_objects

  • Loading branch information...
commit 17559e6eb0422aa6ec7bd9b7f1345b97a2a454a6 1 parent 4fd9496
@spookylukey spookylukey authored
Showing with 22 additions and 25 deletions.
  1. +22 −25 django/db/models/query.py
View
47 django/db/models/query.py
@@ -1545,8 +1545,18 @@ def prefetch_related_objects(result_cache, related_lookups):
if len(obj_list) == 0:
break
+ current_lookup = LOOKUP_SEP.join(attrs[0:level+1])
+ if current_lookup in done_queries:
+ # Skip any prefetching, and any object preparation
+ obj_list = done_queries[current_lookup]
+ continue
+
+ # Prepare objects:
good_objects = True
for obj in obj_list:
+ # Since prefetching can re-use instances, it is possible to have
+ # the same instance multiple times in obj_list, so obj might
+ # already be prepared.
if not hasattr(obj, '_prefetched_objects_cache'):
try:
obj._prefetched_objects_cache = {}
@@ -1557,14 +1567,6 @@ def prefetch_related_objects(result_cache, related_lookups):
# now.
good_objects = False
break
- else:
- # Since prefetching can re-use instances, it is possible to
- # have the same instance multiple times in obj_list. So we
- # can reach this branch either because we did all of
- # obj_list already, or because we did 'obj' earlier in this
- # iteration over obj_list. In the first case we could
- # shortcut and exit the loop, but not in the second.
- continue
if not good_objects:
break
@@ -1589,23 +1591,18 @@ def prefetch_related_objects(result_cache, related_lookups):
"prefetch_related()." % lookup)
if prefetcher is not None and not is_fetched:
- # Check we didn't do this already
- current_lookup = LOOKUP_SEP.join(attrs[0:level+1])
- if current_lookup in done_queries:
- obj_list = done_queries[current_lookup]
- else:
- obj_list, additional_prl = prefetch_one_level(obj_list, prefetcher, attr)
- # We need to ensure we don't keep adding lookups from the
- # same relationships to stop infinite recursion. So, if we
- # are already on an automatically added lookup, don't add
- # the new lookups from relationships we've seen already.
- if not (lookup in auto_lookups and
- descriptor in followed_descriptors):
- for f in additional_prl:
- new_prl = LOOKUP_SEP.join([current_lookup, f])
- auto_lookups.append(new_prl)
- done_queries[current_lookup] = obj_list
- followed_descriptors.add(descriptor)
+ obj_list, additional_prl = prefetch_one_level(obj_list, prefetcher, attr)
+ # We need to ensure we don't keep adding lookups from the
+ # same relationships to stop infinite recursion. So, if we
+ # are already on an automatically added lookup, don't add
+ # the new lookups from relationships we've seen already.
+ if not (lookup in auto_lookups and
+ descriptor in followed_descriptors):
+ for f in additional_prl:
+ new_prl = LOOKUP_SEP.join([current_lookup, f])
+ auto_lookups.append(new_prl)
+ done_queries[current_lookup] = obj_list
+ followed_descriptors.add(descriptor)
else:
# Either a singly related object that has already been fetched
# (e.g. via select_related), or hopefully some other property
Please sign in to comment.
Something went wrong with that request. Please try again.