Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #17439 -- Prevented spurious queries for missing objects after …

…prefetch_related has run.

That affects nullable foreign key, nullable one-to-one, and reverse one-to-one relations.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@17899 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 632b6a1a73bc47226e40dc0a9891c67138a2161c 1 parent e2548ec
Aymeric Augustin authored April 11, 2012
23  django/db/models/query.py
@@ -6,6 +6,7 @@
6 6
 import itertools
7 7
 import sys
8 8
 
  9
+from django.core import exceptions
9 10
 from django.db import connections, router, transaction, IntegrityError
10 11
 from django.db.models.fields import AutoField
11 12
 from django.db.models.query_utils import (Q, select_related_descend,
@@ -1677,12 +1678,19 @@ def prefetch_related_objects(result_cache, related_lookups):
1677 1678
                 # (e.g. via select_related), or hopefully some other property
1678 1679
                 # that doesn't support prefetching but needs to be traversed.
1679 1680
 
1680  
-                # We replace the current list of parent objects with that list.
1681  
-                obj_list = [getattr(obj, attr) for obj in obj_list]
1682  
-
1683  
-                # Filter out 'None' so that we can continue with nullable
1684  
-                # relations.
1685  
-                obj_list = [obj for obj in obj_list if obj is not None]
  1681
+                # We replace the current list of parent objects with the list
  1682
+                # of related objects, filtering out empty or missing values so
  1683
+                # that we can continue with nullable or reverse relations.
  1684
+                new_obj_list = []
  1685
+                for obj in obj_list:
  1686
+                    try:
  1687
+                        new_obj = getattr(obj, attr)
  1688
+                    except exceptions.ObjectDoesNotExist:
  1689
+                        continue
  1690
+                    if new_obj is None:
  1691
+                        continue
  1692
+                    new_obj_list.append(new_obj)
  1693
+                obj_list = new_obj_list
1686 1694
 
1687 1695
 
1688 1696
 def get_prefetcher(instance, attr):
@@ -1778,8 +1786,7 @@ def prefetch_one_level(instances, prefetcher, attname):
1778 1786
         vals = rel_obj_cache.get(instance_attr_val, [])
1779 1787
         if single:
1780 1788
             # Need to assign to single cache on instance
1781  
-            if vals:
1782  
-                setattr(obj, cache_name, vals[0])
  1789
+            setattr(obj, cache_name, vals[0] if vals else None)
1783 1790
         else:
1784 1791
             # Multi, attribute represents a manager with an .all() method that
1785 1792
             # returns a QuerySet
8  tests/modeltests/prefetch_related/tests.py
@@ -68,6 +68,14 @@ def test_foreignkey_reverse(self):

0 notes on commit 632b6a1

Please sign in to comment.
Something went wrong with that request. Please try again.