Commit 65e005f8 authored by Simon Charette's avatar Simon Charette
Browse files

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.
parent 281fc034
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -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):
        """
+17 −0
Original line number Diff line number Diff line
@@ -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
+12 −1
Original line number Diff line number Diff line
@@ -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])