mirror of
https://github.com/django/django.git
synced 2025-05-10 00:46:28 +00:00
[1.5.x] Optimisation in prefetch_related_objects
Backport of 17559e6eb0 from master
This commit is contained in:
parent
00b39e0145
commit
a2eb219556
@ -1713,8 +1713,18 @@ def prefetch_related_objects(result_cache, related_lookups):
|
|||||||
if len(obj_list) == 0:
|
if len(obj_list) == 0:
|
||||||
break
|
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
|
good_objects = True
|
||||||
for obj in obj_list:
|
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'):
|
if not hasattr(obj, '_prefetched_objects_cache'):
|
||||||
try:
|
try:
|
||||||
obj._prefetched_objects_cache = {}
|
obj._prefetched_objects_cache = {}
|
||||||
@ -1725,14 +1735,6 @@ def prefetch_related_objects(result_cache, related_lookups):
|
|||||||
# now.
|
# now.
|
||||||
good_objects = False
|
good_objects = False
|
||||||
break
|
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:
|
if not good_objects:
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -1757,23 +1759,18 @@ def prefetch_related_objects(result_cache, related_lookups):
|
|||||||
"prefetch_related()." % lookup)
|
"prefetch_related()." % lookup)
|
||||||
|
|
||||||
if prefetcher is not None and not is_fetched:
|
if prefetcher is not None and not is_fetched:
|
||||||
# Check we didn't do this already
|
obj_list, additional_prl = prefetch_one_level(obj_list, prefetcher, attr)
|
||||||
current_lookup = LOOKUP_SEP.join(attrs[0:level+1])
|
# We need to ensure we don't keep adding lookups from the
|
||||||
if current_lookup in done_queries:
|
# same relationships to stop infinite recursion. So, if we
|
||||||
obj_list = done_queries[current_lookup]
|
# are already on an automatically added lookup, don't add
|
||||||
else:
|
# the new lookups from relationships we've seen already.
|
||||||
obj_list, additional_prl = prefetch_one_level(obj_list, prefetcher, attr)
|
if not (lookup in auto_lookups and
|
||||||
# We need to ensure we don't keep adding lookups from the
|
descriptor in followed_descriptors):
|
||||||
# same relationships to stop infinite recursion. So, if we
|
for f in additional_prl:
|
||||||
# are already on an automatically added lookup, don't add
|
new_prl = LOOKUP_SEP.join([current_lookup, f])
|
||||||
# the new lookups from relationships we've seen already.
|
auto_lookups.append(new_prl)
|
||||||
if not (lookup in auto_lookups and
|
done_queries[current_lookup] = obj_list
|
||||||
descriptor in followed_descriptors):
|
followed_descriptors.add(descriptor)
|
||||||
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:
|
else:
|
||||||
# Either a singly related object that has already been fetched
|
# Either a singly related object that has already been fetched
|
||||||
# (e.g. via select_related), or hopefully some other property
|
# (e.g. via select_related), or hopefully some other property
|
||||||
|
Loading…
x
Reference in New Issue
Block a user