mirror of
https://github.com/Hopiu/django-model-utils.git
synced 2026-03-17 04:10:24 +00:00
Merge pull request #89 from kezabelle/bugfix/named_onetoone
Allow InheritanceManager to work with manually specified OneToOnes
This commit is contained in:
commit
3b5c99b093
3 changed files with 114 additions and 6 deletions
|
|
@ -110,8 +110,8 @@ class InheritanceQuerySet(QuerySet):
|
|||
if levels or levels is None:
|
||||
for subclass in self._get_subclasses_recurse(
|
||||
rel.field.model, levels=levels):
|
||||
subclasses.append(rel.var_name + LOOKUP_SEP + subclass)
|
||||
subclasses.append(rel.var_name)
|
||||
subclasses.append(rel.get_accessor_name() + LOOKUP_SEP + subclass)
|
||||
subclasses.append(rel.get_accessor_name())
|
||||
return subclasses
|
||||
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ class InheritanceQuerySet(QuerySet):
|
|||
if levels:
|
||||
levels -= 1
|
||||
while parent is not None:
|
||||
ancestry.insert(0, parent.related.var_name)
|
||||
ancestry.insert(0, parent.related.get_accessor_name())
|
||||
if levels or levels is None:
|
||||
parent = parent.related.parent_model._meta.get_ancestor_link(
|
||||
self.model)
|
||||
|
|
|
|||
|
|
@ -44,20 +44,29 @@ class InheritanceManagerTestChild1(InheritanceManagerTestParent):
|
|||
objects = InheritanceManager()
|
||||
|
||||
|
||||
|
||||
class InheritanceManagerTestGrandChild1(InheritanceManagerTestChild1):
|
||||
text_field = models.TextField()
|
||||
|
||||
|
||||
|
||||
class InheritanceManagerTestGrandChild1_2(InheritanceManagerTestChild1):
|
||||
text_field = models.TextField()
|
||||
|
||||
|
||||
|
||||
class InheritanceManagerTestChild2(InheritanceManagerTestParent):
|
||||
non_related_field_using_descriptor_2 = models.FileField(upload_to="test")
|
||||
normal_field_2 = models.TextField()
|
||||
|
||||
|
||||
|
||||
class InheritanceManagerTestChild3(InheritanceManagerTestParent):
|
||||
parent_ptr = models.OneToOneField(
|
||||
InheritanceManagerTestParent, related_name='manual_onetoone',
|
||||
parent_link=True)
|
||||
|
||||
|
||||
class TimeStamp(TimeStampedModel):
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ from model_utils.tests.models import (
|
|||
TimeFrameManagerAdded, Dude, SplitFieldAbstractParent, Car, Spot,
|
||||
ModelTracked, ModelTrackedFK, ModelTrackedNotDefault, ModelTrackedMultiple, InheritedModelTracked,
|
||||
Tracked, TrackedFK, TrackedNotDefault, TrackedNonFieldAttr, TrackedMultiple,
|
||||
InheritedTracked, StatusFieldDefaultFilled, StatusFieldDefaultNotFilled)
|
||||
InheritedTracked, StatusFieldDefaultFilled, StatusFieldDefaultNotFilled,
|
||||
InheritanceManagerTestChild3)
|
||||
|
||||
|
||||
class GetExcerptTests(TestCase):
|
||||
|
|
@ -683,6 +684,76 @@ class InheritanceManagerTests(TestCase):
|
|||
self.assertEqual(1, self.get_manager().all()._get_maximum_depth())
|
||||
|
||||
|
||||
@skipUnless(django.VERSION < (1, 6, 0), "test only applies to Django < 1.6")
|
||||
def test_manually_specifying_parent_fk_only_children(self):
|
||||
"""
|
||||
given a Model which inherits from another Model, but also declares
|
||||
the OneToOne link manually using `related_name` and `parent_link`,
|
||||
ensure that the relation names and subclasses are obtained correctly.
|
||||
"""
|
||||
child3 = InheritanceManagerTestChild3.objects.create()
|
||||
results = InheritanceManagerTestParent.objects.all().select_subclasses()
|
||||
|
||||
expected_objs = [self.child1, self.child2,
|
||||
InheritanceManagerTestChild1(pk=self.grandchild1.pk),
|
||||
InheritanceManagerTestChild1(pk=self.grandchild1_2.pk),
|
||||
child3]
|
||||
self.assertEqual(list(results), expected_objs)
|
||||
|
||||
expected_related_names = [
|
||||
'inheritancemanagertestchild1',
|
||||
'inheritancemanagertestchild2',
|
||||
'manual_onetoone', # this was set via parent_link & related_name
|
||||
]
|
||||
self.assertEqual(set(results.subclasses),
|
||||
set(expected_related_names))
|
||||
|
||||
|
||||
@skipUnless(django.VERSION >= (1, 6, 0), "test only applies to Django 1.6+")
|
||||
def test_manually_specifying_parent_fk_including_grandchildren(self):
|
||||
"""
|
||||
given a Model which inherits from another Model, but also declares
|
||||
the OneToOne link manually using `related_name` and `parent_link`,
|
||||
ensure that the relation names and subclasses are obtained correctly.
|
||||
"""
|
||||
child3 = InheritanceManagerTestChild3.objects.create()
|
||||
results = InheritanceManagerTestParent.objects.all().select_subclasses()
|
||||
|
||||
expected_objs = [self.child1, self.child2, self.grandchild1,
|
||||
self.grandchild1_2, child3]
|
||||
self.assertEqual(list(results), expected_objs)
|
||||
|
||||
expected_related_names = [
|
||||
'inheritancemanagertestchild1__inheritancemanagertestgrandchild1',
|
||||
'inheritancemanagertestchild1__inheritancemanagertestgrandchild1_2',
|
||||
'inheritancemanagertestchild1',
|
||||
'inheritancemanagertestchild2',
|
||||
'manual_onetoone', # this was set via parent_link & related_name
|
||||
]
|
||||
self.assertEqual(set(results.subclasses),
|
||||
set(expected_related_names))
|
||||
|
||||
|
||||
def test_manually_specifying_parent_fk_single_subclass(self):
|
||||
"""
|
||||
Using a string related_name when the relation is manually defined
|
||||
instead of implicit should still work in the same way.
|
||||
"""
|
||||
related_name = 'manual_onetoone'
|
||||
child3 = InheritanceManagerTestChild3.objects.create()
|
||||
results = InheritanceManagerTestParent.objects.all().select_subclasses(related_name)
|
||||
|
||||
expected_objs = [InheritanceManagerTestParent(pk=self.child1.pk),
|
||||
InheritanceManagerTestParent(pk=self.child2.pk),
|
||||
InheritanceManagerTestParent(pk=self.grandchild1.pk),
|
||||
InheritanceManagerTestParent(pk=self.grandchild1_2.pk),
|
||||
child3]
|
||||
self.assertEqual(list(results), expected_objs)
|
||||
expected_related_names = [related_name]
|
||||
self.assertEqual(set(results.subclasses),
|
||||
set(expected_related_names))
|
||||
|
||||
|
||||
class InheritanceManagerUsingModelsTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
|
@ -731,6 +802,7 @@ class InheritanceManagerUsingModelsTests(TestCase):
|
|||
objs = InheritanceManagerTestParent.objects.select_subclasses().order_by('pk')
|
||||
objsmodels = InheritanceManagerTestParent.objects.select_subclasses(
|
||||
InheritanceManagerTestChild1, InheritanceManagerTestChild2,
|
||||
InheritanceManagerTestChild3,
|
||||
InheritanceManagerTestGrandChild1,
|
||||
InheritanceManagerTestGrandChild1_2).order_by('pk')
|
||||
self.assertEqual(set(objs.subclasses), set(objsmodels.subclasses))
|
||||
|
|
@ -751,11 +823,15 @@ class InheritanceManagerUsingModelsTests(TestCase):
|
|||
objs = InheritanceManagerTestParent.objects.select_subclasses().order_by('pk')
|
||||
|
||||
if django.VERSION >= (1, 6, 0):
|
||||
models = (InheritanceManagerTestChild1, InheritanceManagerTestChild2,
|
||||
models = (InheritanceManagerTestChild1,
|
||||
InheritanceManagerTestChild2,
|
||||
InheritanceManagerTestChild3,
|
||||
InheritanceManagerTestGrandChild1,
|
||||
InheritanceManagerTestGrandChild1_2)
|
||||
else:
|
||||
models = (InheritanceManagerTestChild1, InheritanceManagerTestChild2)
|
||||
models = (InheritanceManagerTestChild1,
|
||||
InheritanceManagerTestChild2,
|
||||
InheritanceManagerTestChild3)
|
||||
|
||||
objsmodels = InheritanceManagerTestParent.objects.select_subclasses(
|
||||
*models).order_by('pk')
|
||||
|
|
@ -873,6 +949,29 @@ class InheritanceManagerUsingModelsTests(TestCase):
|
|||
], list(objs))
|
||||
|
||||
|
||||
def test_manually_specifying_parent_fk_only_specific_child(self):
|
||||
"""
|
||||
given a Model which inherits from another Model, but also declares
|
||||
the OneToOne link manually using `related_name` and `parent_link`,
|
||||
ensure that the relation names and subclasses are obtained correctly.
|
||||
"""
|
||||
child3 = InheritanceManagerTestChild3.objects.create()
|
||||
results = InheritanceManagerTestParent.objects.all().select_subclasses(
|
||||
InheritanceManagerTestChild3)
|
||||
|
||||
expected_objs = [InheritanceManagerTestParent(pk=self.parent1.pk),
|
||||
InheritanceManagerTestParent(pk=self.child1.pk),
|
||||
InheritanceManagerTestParent(pk=self.child2.pk),
|
||||
InheritanceManagerTestParent(pk=self.grandchild1.pk),
|
||||
InheritanceManagerTestParent(pk=self.grandchild1_2.pk),
|
||||
child3]
|
||||
self.assertEqual(list(results), expected_objs)
|
||||
|
||||
expected_related_names = ['manual_onetoone']
|
||||
self.assertEqual(set(results.subclasses),
|
||||
set(expected_related_names))
|
||||
|
||||
|
||||
|
||||
class InheritanceManagerRelatedTests(InheritanceManagerTests):
|
||||
def setUp(self):
|
||||
|
|
|
|||
Loading…
Reference in a new issue