From 6f30e88ba5421c8c01b200ddc4abb70132195838 Mon Sep 17 00:00:00 2001 From: Curtis Date: Wed, 8 Jan 2014 15:12:55 +1100 Subject: [PATCH 1/6] Attempt to carry over extras(select) values from parent --- model_utils/managers.py | 4 ++++ model_utils/tests/tests.py | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/model_utils/managers.py b/model_utils/managers.py index 1f01465..19a1425 100644 --- a/model_utils/managers.py +++ b/model_utils/managers.py @@ -70,6 +70,7 @@ class InheritanceQuerySet(QuerySet): def iterator(self): iter = super(InheritanceQuerySet, self).iterator() if getattr(self, 'subclasses', False): + extras = self.query.extra_select.keys() # sort the subclass names longest first, # so with 'a' and 'a__b' it goes as deep as possible subclasses = sorted(self.subclasses, key=len, reverse=True) @@ -86,6 +87,9 @@ class InheritanceQuerySet(QuerySet): for k in self._annotated: setattr(sub_obj, k, getattr(obj, k)) + for k in extras: + setattr(sub_obj, k, getattr(obj, k)) + yield sub_obj else: for obj in iter: diff --git a/model_utils/tests/tests.py b/model_utils/tests/tests.py index 070ba46..bbc0e37 100644 --- a/model_utils/tests/tests.py +++ b/model_utils/tests/tests.py @@ -974,6 +974,15 @@ class InheritanceManagerUsingModelsTests(TestCase): self.assertEqual(set(results.subclasses), set(expected_related_names)) + def test_extras_descend(self): + """ + Ensure that if extras(select=) is passed, we copy the values down onto + sub classes. + """ + results = InheritanceManagerTestParent.objects.all().extra( + select={'foo': 'id + 1'} + ) + self.assertTrue(all(result.foo == (result.id + 1) for result in results)) class InheritanceManagerRelatedTests(InheritanceManagerTests): From 0e77c327f58293d7f6067a7465495982984a0ce8 Mon Sep 17 00:00:00 2001 From: Curtis Maloney Date: Thu, 9 Jan 2014 15:46:11 +1100 Subject: [PATCH 2/6] Update tests.py --- model_utils/tests/tests.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/model_utils/tests/tests.py b/model_utils/tests/tests.py index bbc0e37..3dccaea 100644 --- a/model_utils/tests/tests.py +++ b/model_utils/tests/tests.py @@ -976,10 +976,9 @@ class InheritanceManagerUsingModelsTests(TestCase): def test_extras_descend(self): """ - Ensure that if extras(select=) is passed, we copy the values down onto - sub classes. + Ensure that when extra(select=) is passed the values appear on sub-classes. """ - results = InheritanceManagerTestParent.objects.all().extra( + results = InheritanceManagerTestParent.objects.select_subclasses().extra( select={'foo': 'id + 1'} ) self.assertTrue(all(result.foo == (result.id + 1) for result in results)) From cb362f4a12f99e921aef6fd12b3119f60914765a Mon Sep 17 00:00:00 2001 From: funkybob Date: Mon, 13 Jan 2014 16:49:18 +1100 Subject: [PATCH 3/6] Shorten test docstring --- model_utils/tests/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model_utils/tests/tests.py b/model_utils/tests/tests.py index 3dccaea..abad8e1 100644 --- a/model_utils/tests/tests.py +++ b/model_utils/tests/tests.py @@ -976,7 +976,7 @@ class InheritanceManagerUsingModelsTests(TestCase): def test_extras_descend(self): """ - Ensure that when extra(select=) is passed the values appear on sub-classes. + Ensure that extra(select=) values are copied onto sub-classes. """ results = InheritanceManagerTestParent.objects.select_subclasses().extra( select={'foo': 'id + 1'} From 91b07079e0dfc1ae257d8c17a9fcb1aae6902edc Mon Sep 17 00:00:00 2001 From: funkybob Date: Tue, 14 Jan 2014 15:05:03 +1100 Subject: [PATCH 4/6] Use legacy compatible approach --- model_utils/managers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model_utils/managers.py b/model_utils/managers.py index 19a1425..28410d3 100644 --- a/model_utils/managers.py +++ b/model_utils/managers.py @@ -70,7 +70,7 @@ class InheritanceQuerySet(QuerySet): def iterator(self): iter = super(InheritanceQuerySet, self).iterator() if getattr(self, 'subclasses', False): - extras = self.query.extra_select.keys() + extras = self.query.extra.keys() # sort the subclass names longest first, # so with 'a' and 'a__b' it goes as deep as possible subclasses = sorted(self.subclasses, key=len, reverse=True) From a5fe3de330a3c7e8b112c5f1107cbbe383ea5efd Mon Sep 17 00:00:00 2001 From: funkybob Date: Tue, 21 Jan 2014 09:19:54 +1100 Subject: [PATCH 5/6] Deal with Django <1.7 using SortedDict wherein keys() is a generator, not a view --- model_utils/managers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model_utils/managers.py b/model_utils/managers.py index 28410d3..93d6d48 100644 --- a/model_utils/managers.py +++ b/model_utils/managers.py @@ -70,7 +70,7 @@ class InheritanceQuerySet(QuerySet): def iterator(self): iter = super(InheritanceQuerySet, self).iterator() if getattr(self, 'subclasses', False): - extras = self.query.extra.keys() + extras = tuple(self.query.extra.keys()) # sort the subclass names longest first, # so with 'a' and 'a__b' it goes as deep as possible subclasses = sorted(self.subclasses, key=len, reverse=True) From 5b6a3ff197933be06dc3fc25f35a4d0073da186f Mon Sep 17 00:00:00 2001 From: funkybob Date: Tue, 21 Jan 2014 11:08:28 +1100 Subject: [PATCH 6/6] Update AUTHORS and CHANGES --- AUTHORS.rst | 1 + CHANGES.rst | 2 ++ 2 files changed, 3 insertions(+) diff --git a/AUTHORS.rst b/AUTHORS.rst index 6d57e7d..931c8cd 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -24,3 +24,4 @@ Travis Swicegood Trey Hunner zyegfryed Filipe Ximenes +Curtis Maloney diff --git a/CHANGES.rst b/CHANGES.rst index ee72232..7f0834b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -36,6 +36,8 @@ master (unreleased) * MonitorField now accepts a 'when' parameter. It will update only when the field changes to one of the values specified. +* Improve `InheritanceManager` so any attributes added by using extra(select) + will be propagated onto children. 1.5.0 (2013.08.29) ------------------