Fixed #17485 regression -- only + select_related interaction

When doing deeper than one level select_related() + only queries(), the
code introduced in b6c356b7bb errored
incorrectly.

Thanks to mrmachine for report & test case.
This commit is contained in:
Anssi Kääriäinen 2012-09-15 21:11:14 +03:00
parent 935a8635c2
commit f399a804c9
3 changed files with 23 additions and 2 deletions

View File

@ -609,8 +609,12 @@ class SQLCompiler(object):
restricted = False
for f, model in opts.get_fields_with_model():
# The get_fields_with_model() returns None for fields that live
# in the field's local model. So, for those fields we want to use
# the f.model - that is the field's local model.
field_model = model or f.model
if not select_related_descend(f, restricted, requested,
only_load.get(model or self.query.model)):
only_load.get(field_model)):
continue
# The "avoid" set is aliases we want to avoid just for this
# particular branch of the recursion. They aren't permanently

View File

@ -52,6 +52,9 @@ class SimpleItem(models.Model):
class Feature(models.Model):
item = models.ForeignKey(SimpleItem)
class SpecialFeature(models.Model):
feature = models.ForeignKey(Feature)
class ItemAndSimpleItem(models.Model):
item = models.ForeignKey(Item)
simple = models.ForeignKey(SimpleItem)

View File

@ -9,7 +9,7 @@ from django.db.models.loading import cache
from django.test import TestCase
from .models import (ResolveThis, Item, RelatedItem, Child, Leaf, Proxy,
SimpleItem, Feature, ItemAndSimpleItem)
SimpleItem, Feature, ItemAndSimpleItem, SpecialFeature)
class DeferRegressionTest(TestCase):
@ -115,6 +115,7 @@ class DeferRegressionTest(TestCase):
RelatedItem,
ResolveThis,
SimpleItem,
SpecialFeature,
]
)
@ -152,6 +153,7 @@ class DeferRegressionTest(TestCase):
"RelatedItem_Deferred_item_id",
"ResolveThis",
"SimpleItem",
"SpecialFeature",
]
)
@ -197,6 +199,18 @@ class DeferRegressionTest(TestCase):
self.assertEqual(obj.item, item2)
self.assertEqual(obj.item_id, item2.id)
def test_only_with_select_related(self):
# Test for #17485.
item = SimpleItem.objects.create(name='first', value=47)
feature = Feature.objects.create(item=item)
SpecialFeature.objects.create(feature=feature)
qs = Feature.objects.only('item__name').select_related('item')
self.assertEqual(len(qs), 1)
qs = SpecialFeature.objects.only('feature__item__name').select_related('feature__item')
self.assertEqual(len(qs), 1)
def test_deferred_class_factory(self):
from django.db.models.query_utils import deferred_class_factory
new_class = deferred_class_factory(Item,