Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

queryset-refactor: Second part of select_related() fix.

Relations on the parent model can now be specified as part of the fields list.
Fixed #6761.


git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7241 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 59ac04a54dde3a489f7948b6e6d6170d74aa80c8 1 parent cf2da46
Malcolm Tredinnick authored March 14, 2008
20  django/db/models/sql/query.py
@@ -769,10 +769,10 @@ def fill_related_selections(self, opts=None, root_alias=None, cur_depth=1,
769 769
             return
770 770
         if not opts:
771 771
             opts = self.get_meta()
772  
-            root_alias = self.tables[0]
  772
+            root_alias = self.get_initial_alias()
773 773
             self.select.extend(self.get_default_columns())
774 774
         if not used:
775  
-            used = []
  775
+            used = set()
776 776
 
777 777
         # Setup for the case when only particular related fields should be
778 778
         # included in the related selection.
@@ -783,14 +783,24 @@ def fill_related_selections(self, opts=None, root_alias=None, cur_depth=1,
783 783
             else:
784 784
                 restricted = False
785 785
 
786  
-        for f in opts.fields:
  786
+        for f, model in opts.get_fields_with_model():
787 787
             if (not f.rel or (restricted and f.name not in requested) or
788 788
                     (not restricted and f.null) or f.rel.parent_link):
789 789
                 continue
790 790
             table = f.rel.to._meta.db_table
791  
-            alias = self.join((root_alias, table, f.column,
  791
+            if model:
  792
+                int_opts = opts
  793
+                alias = root_alias
  794
+                for int_model in opts.get_base_chain(model):
  795
+                    lhs_col = int_opts.parents[int_model].column
  796
+                    int_opts = int_model._meta
  797
+                    alias = self.join((alias, int_opts.db_table, lhs_col,
  798
+                            int_opts.pk.column), exclusions=used)
  799
+            else:
  800
+                alias = root_alias
  801
+            alias = self.join((alias, table, f.column,
792 802
                     f.rel.get_related_field().column), exclusions=used)
793  
-            used.append(alias)
  803
+            used.add(alias)
794 804
             self.select.extend([(alias, f2.column)
795 805
                     for f2 in f.rel.to._meta.fields])
796 806
             if restricted:
32  tests/modeltests/model_inheritance/models.py
@@ -42,6 +42,12 @@ class Meta:
42 42
 # Multi-table inheritance
43 43
 #
44 44
 
  45
+class Chef(models.Model):
  46
+    name = models.CharField(max_length=50)
  47
+
  48
+    def __unicode__(self):
  49
+        return u"%s the chef" % self.name
  50
+
45 51
 class Place(models.Model):
46 52
     name = models.CharField(max_length=50)
47 53
     address = models.CharField(max_length=80)
@@ -59,6 +65,7 @@ class Meta:
59 65
 class Restaurant(Place, Rating):
60 66
     serves_hot_dogs = models.BooleanField()
61 67
     serves_pizza = models.BooleanField()
  68
+    chef = models.ForeignKey(Chef, null=True, blank=True)
62 69
 
63 70
     class Meta(Rating.Meta):
64 71
         db_table = 'my_restaurant'
@@ -136,7 +143,9 @@ def __unicode__(self):
136 143
 >>> r.save()
137 144
 
138 145
 # Test the constructor for ItalianRestaurant.
139  
->>> ir = ItalianRestaurant(name='Ristorante Miron', address='1234 W. Ash', serves_hot_dogs=False, serves_pizza=False, serves_gnocchi=True, rating=4)
  146
+>>> c = Chef(name="Albert")
  147
+>>> c.save()
  148
+>>> ir = ItalianRestaurant(name='Ristorante Miron', address='1234 W. Ash', serves_hot_dogs=False, serves_pizza=False, serves_gnocchi=True, rating=4, chef=c)
140 149
 >>> ir.save()
141 150
 >>> ir.address = '1234 W. Elm'
142 151
 >>> ir.save()
@@ -144,9 +153,9 @@ def __unicode__(self):
144 153
 # Make sure Restaurant and ItalianRestaurant have the right fields in the right
145 154
 # order.
146 155
 >>> [f.name for f in Restaurant._meta.fields]
147  
-['id', 'name', 'address', 'place_ptr', 'rating', 'serves_hot_dogs', 'serves_pizza']
  156
+['id', 'name', 'address', 'place_ptr', 'rating', 'serves_hot_dogs', 'serves_pizza', 'chef']
148 157
 >>> [f.name for f in ItalianRestaurant._meta.fields]
149  
-['id', 'name', 'address', 'place_ptr', 'rating', 'serves_hot_dogs', 'serves_pizza', 'restaurant_ptr', 'serves_gnocchi']
  158
+['id', 'name', 'address', 'place_ptr', 'rating', 'serves_hot_dogs', 'serves_pizza', 'chef', 'restaurant_ptr', 'serves_gnocchi']
150 159
 >>> Restaurant._meta.ordering
151 160
 ['-rating']
152 161
 
@@ -158,7 +167,7 @@ def __unicode__(self):
158 167
 >>> Restaurant.objects.filter(supplier__name='foo')
159 168
 Traceback (most recent call last):
160 169
     ...
161  
-FieldError: Cannot resolve keyword 'supplier' into field. Choices are: address, id, italianrestaurant, lot, name, place_ptr, provider, rating, serves_hot_dogs, serves_pizza
  170
+FieldError: Cannot resolve keyword 'supplier' into field. Choices are: address, chef, id, italianrestaurant, lot, name, place_ptr, provider, rating, serves_hot_dogs, serves_pizza
162 171
 
163 172
 # Parent fields can be used directly in filters on the child model.
164 173
 >>> Restaurant.objects.filter(name='Demon Dogs')
@@ -240,4 +249,19 @@ def __unicode__(self):
240 249
 >>> list(ItalianRestaurant.objects.values('name', 'rating')) == [d]
241 250
 True
242 251
 
  252
+# select_related works with fields from the parent object as if they were a
  253
+# normal part of the model.
  254
+>>> from django import db
  255
+>>> from django.conf import settings
  256
+>>> settings.DEBUG = True
  257
+>>> db.reset_queries()
  258
+>>> ItalianRestaurant.objects.all()[0].chef
  259
+<Chef: Albert the chef>
  260
+>>> len(db.connection.queries)
  261
+2
  262
+>>> ItalianRestaurant.objects.select_related('chef')[0].chef
  263
+<Chef: Albert the chef>
  264
+>>> len(db.connection.queries)
  265
+3
  266
+
243 267
 """}

0 notes on commit 59ac04a

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