Fix bug with child/grandchild select_subclasses in Django 1.6+; thanks Keryn Knight.

This commit is contained in:
Carl Meyer 2013-09-20 10:04:10 -06:00
parent 8bead336a7
commit 4b6a800050
4 changed files with 39 additions and 4 deletions

View file

@ -4,6 +4,10 @@ CHANGES
master (unreleased)
-------------------
* Fix bug in `InheritanceManager` with grandchild classes on Django 1.6+;
`select_subclasses('child', 'child__grandchild')` would only ever get to the
child class. Thanks Keryn Knight for report and proposed fix.
1.5.0 (2013.08.29)
------------------

View file

@ -46,9 +46,12 @@ class InheritanceQuerySet(QuerySet):
def iterator(self):
iter = super(InheritanceQuerySet, self).iterator()
if getattr(self, 'subclasses', False):
# 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)
for obj in iter:
sub_obj = None
for s in self.subclasses:
for s in subclasses:
sub_obj = self._get_sub_obj_recurse(obj, s)
if sub_obj:
break

View file

@ -1,4 +1,7 @@
from __future__ import unicode_literals
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from model_utils.models import TimeStampedModel, StatusModel, TimeFramedModel
@ -15,6 +18,7 @@ class InheritanceManagerTestRelated(models.Model):
@python_2_unicode_compatible
class InheritanceManagerTestParent(models.Model):
# FileField is just a handy descriptor-using field. Refs #6.
non_related_field_using_descriptor = models.FileField(upload_to="test")
@ -24,11 +28,17 @@ class InheritanceManagerTestParent(models.Model):
objects = InheritanceManager()
def __str__(self):
return "%s(%s)" % (
self.__class__.__name__[len('InheritanceManagerTest'):],
self.pk,
)
class InheritanceManagerTestChild1(InheritanceManagerTestParent):
non_related_field_using_descriptor_2 = models.FileField(upload_to="test")
normal_field_2 = models.TextField()
pass
class InheritanceManagerTestGrandChild1(InheritanceManagerTestChild1):

View file

@ -542,8 +542,26 @@ class InheritanceManagerTests(TestCase):
self.assertEqual(
set(
self.get_manager().select_subclasses(
"inheritancemanagertestchild1__"
"inheritancemanagertestgrandchild1"
"inheritancemanagertestchild1__inheritancemanagertestgrandchild1"
)
),
children,
)
@skipUnless(django.VERSION >= (1, 6, 0), "test only applies to Django 1.6+")
def test_children_and_grandchildren(self):
children = set([
self.child1,
InheritanceManagerTestParent(pk=self.child2.pk),
self.grandchild1,
InheritanceManagerTestChild1(pk=self.grandchild1_2.pk),
])
self.assertEqual(
set(
self.get_manager().select_subclasses(
"inheritancemanagertestchild1",
"inheritancemanagertestchild1__inheritancemanagertestgrandchild1"
)
),
children,