Fixed #24266 -- Changed get_parent_list to return a list ordered by MRO.

Thanks to Aron Podrigal for the initial patch and Tim for the review.
This commit is contained in:
Simon Charette 2015-02-03 15:13:43 -05:00
parent 281fc03474
commit 65e005f8cd
3 changed files with 36 additions and 8 deletions

View File

@ -12,7 +12,7 @@ from django.db.models.fields.related import ManyToManyField
from django.db.models.fields import AutoField
from django.db.models.fields.proxy import OrderWrt
from django.utils import six
from django.utils.datastructures import ImmutableList
from django.utils.datastructures import ImmutableList, OrderedSet
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible
from django.utils.functional import cached_property
@ -634,14 +634,14 @@ class Options(object):
def get_parent_list(self):
"""
Returns a list of all the ancestor of this model as a list. Useful for
determining if something is an ancestor, regardless of lineage.
Returns all the ancestors of this model as a list ordered by MRO.
Useful for determining if something is an ancestor, regardless of lineage.
"""
result = set()
result = OrderedSet(self.parents)
for parent in self.parents:
result.add(parent)
result.update(parent._meta.get_parent_list())
return result
for ancestor in parent._meta.get_parent_list():
result.add(ancestor)
return list(result)
def get_ancestor_link(self, ancestor):
"""

View File

@ -118,3 +118,20 @@ class Relating(models.Model):
# ManyToManyField to Person
people = models.ManyToManyField(Person, related_name='relating_people')
people_hidden = models.ManyToManyField(Person, related_name='+')
# ParentListTests models
class CommonAncestor(models.Model):
pass
class FirstParent(CommonAncestor):
first_ancestor = models.OneToOneField(CommonAncestor, primary_key=True, parent_link=True)
class SecondParent(CommonAncestor):
second_ancestor = models.OneToOneField(CommonAncestor, primary_key=True, parent_link=True)
class Child(FirstParent, SecondParent):
pass

View File

@ -5,7 +5,10 @@ from django.db.models.fields import related, CharField, Field
from django.db.models.options import IMMUTABLE_WARNING, EMPTY_RELATION_TREE
from django.test import TestCase
from .models import Relation, AbstractPerson, BasePerson, Person, ProxyPerson, Relating
from .models import (
Relation, AbstractPerson, BasePerson, Person, ProxyPerson, Relating,
CommonAncestor, FirstParent, SecondParent, Child
)
from .results import TEST_RESULTS
@ -245,3 +248,11 @@ class RelationTreeTests(TestCase):
])
)
self.assertEqual([field.related_query_name() for field in AbstractPerson._meta._relation_tree], [])
class ParentListTests(TestCase):
def test_get_parent_list(self):
self.assertEqual(CommonAncestor._meta.get_parent_list(), [])
self.assertEqual(FirstParent._meta.get_parent_list(), [CommonAncestor])
self.assertEqual(SecondParent._meta.get_parent_list(), [CommonAncestor])
self.assertEqual(Child._meta.get_parent_list(), [FirstParent, SecondParent, CommonAncestor])