From e9d0ef19bc87aafd71d513cd927db2655267809b Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Sat, 10 May 2014 16:39:20 +0200 Subject: [PATCH] [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 --- django/db/models/query.py | 3 +++ tests/select_related_regress/tests.py | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/django/db/models/query.py b/django/db/models/query.py index 043eac908b..abe882eaeb 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -291,6 +291,9 @@ class QuerySet(object): # Add the known related objects to the model, if there are any if self._known_related_objects: 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()) try: rel_obj = rel_objs[pk] diff --git a/tests/select_related_regress/tests.py b/tests/select_related_regress/tests.py index 78d5838109..6b064ca582 100644 --- a/tests/select_related_regress/tests.py +++ b/tests/select_related_regress/tests.py @@ -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_a.name, 'a') 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