[1.7.x] Fixed #22508 -- Avoided overwriting select_related.

Previously, known related objects overwrote related objects loaded
though select_related. This could cancel the effect of select_related
when it was used over more than one level.

Thanks boxm for the bug report and timo for bisecting the regression.

Backport of f574220f from master
This commit is contained in:
Aymeric Augustin 2014-05-10 16:39:20 +02:00
parent c54fb3d922
commit e9d0ef19bc
2 changed files with 13 additions and 0 deletions

View File

@ -291,6 +291,9 @@ class QuerySet(object):
# Add the known related objects to the model, if there are any # Add the known related objects to the model, if there are any
if self._known_related_objects: if self._known_related_objects:
for field, rel_objs in self._known_related_objects.items(): for field, rel_objs in self._known_related_objects.items():
# Avoid overwriting objects loaded e.g. by select_related
if hasattr(obj, field.get_cache_name()):
continue
pk = getattr(obj, field.get_attname()) pk = getattr(obj, field.get_attname())
try: try:
rel_obj = rel_objs[pk] rel_obj = rel_objs[pk]

View File

@ -188,3 +188,13 @@ class SelectRelatedRegressTests(TestCase):
self.assertEqual(qs_c.c_b.lots_of_text, 'lots_of_text_b') self.assertEqual(qs_c.c_b.lots_of_text, 'lots_of_text_b')
self.assertEqual(qs_c.c_a.name, 'a') self.assertEqual(qs_c.c_a.name, 'a')
self.assertEqual(qs_c.c_b.name, 'b') self.assertEqual(qs_c.c_b.name, 'b')
def test_regression_22508(self):
building = Building.objects.create(name='101')
device = Device.objects.create(name="router", building=building)
Port.objects.create(port_number='1', device=device)
device = Device.objects.get()
port = device.port_set.select_related('device__building').get()
with self.assertNumQueries(0):
port.device.building