diff --git a/AUTHORS.rst b/AUTHORS.rst index f518600..2ef32c3 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -25,3 +25,4 @@ Travis Swicegood Trey Hunner zyegfryed Filipe Ximenes +Curtis Maloney diff --git a/CHANGES.rst b/CHANGES.rst index 0d9c81e..53e6e70 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -42,6 +42,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) ------------------ diff --git a/model_utils/managers.py b/model_utils/managers.py index 2785d2f..2c8810b 100644 --- a/model_utils/managers.py +++ b/model_utils/managers.py @@ -70,6 +70,7 @@ class InheritanceQuerySetMixin(object): def iterator(self): iter = super(InheritanceQuerySetMixin, self).iterator() if getattr(self, 'subclasses', False): + 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) @@ -86,6 +87,9 @@ class InheritanceQuerySetMixin(object): 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..abad8e1 100644 --- a/model_utils/tests/tests.py +++ b/model_utils/tests/tests.py @@ -974,6 +974,14 @@ class InheritanceManagerUsingModelsTests(TestCase): self.assertEqual(set(results.subclasses), set(expected_related_names)) + def test_extras_descend(self): + """ + Ensure that extra(select=) values are copied onto sub-classes. + """ + results = InheritanceManagerTestParent.objects.select_subclasses().extra( + select={'foo': 'id + 1'} + ) + self.assertTrue(all(result.foo == (result.id + 1) for result in results)) class InheritanceManagerRelatedTests(InheritanceManagerTests):