在Django的,当你有一个父类和多个子类继承它,你通常会通过parentclass.childclass1_set或parentclass.childclass2_set,但什么访问一个孩子,如果我不知道具体的子类的名称我想要的吗?

有没有办法让在父母与相关对象>子方向,而不知道子类的名字吗?

有帮助吗?

解决方案

(的更新:对于Django的1.2和更新的,这可以按照跨越反向OneToOneField关系select_related查询(和由此向下继承层次结构),有可用的较好技术,该技术不需要附加real_type场父模型。它可以作为 InheritanceManager django的模型-utils的项目。)

在通常的方式做到这一点是添加一个ForeignKey到CONTENTTYPE上存储有适当的“叶”类的内容类型的父模型。没有这一点,你可能需要做相当多的查询在子表中找到例子,根据您的继承树有多大。以下是我做的一个项目:

from django.contrib.contenttypes.models import ContentType
from django.db import models

class InheritanceCastModel(models.Model):
    """
    An abstract base class that provides a ``real_type`` FK to ContentType.

    For use in trees of inherited models, to be able to downcast
    parent instances to their child types.

    """
    real_type = models.ForeignKey(ContentType, editable=False)

    def save(self, *args, **kwargs):
        if not self._state.adding:
            self.real_type = self._get_real_type()
        super(InheritanceCastModel, self).save(*args, **kwargs)

    def _get_real_type(self):
        return ContentType.objects.get_for_model(type(self))

    def cast(self):
        return self.real_type.get_object_for_this_type(pk=self.pk)

    class Meta:
        abstract = True

这是这样实现的一个抽象基类,使之可重复使用的;你也可以把这些方法和FK直接到父类中的特定的继承层次。

如果你不能够修改父模型该解决方案将无法工作。在这种情况下,你几乎陷入手动检查所有的子类。

其他提示

在Python中,赋予了(“新式”)类X,你可以得到它(直接)与子类X.__subclasses__(),返回类对象的列表。 (如果你想“进一步的后裔”,你还必须调用每个直接的子类,等等等等的__subclasses__ - !如果您需要关于如何有效地做到这一点在Python帮助,只问)。

一旦你以某种方式确定了子类的利益(也许所有的人,如果你希望所有的孩子子类等的情况下),getattr(parentclass,'%s_set' % childclass.__name__)应该帮助(如果该子类的名字是'foo',这就像访问parentclass.foo_set - - 无多,不会少)。同样,如果你需要澄清或实例,请咨询!

卡尔的解决方案是一个很好的一个,这里是做手工,如果有多个相关的子类的一种方式:

def get_children(self):
    rel_objs = self._meta.get_all_related_objects()
    return [getattr(self, x.get_accessor_name()) for x in rel_objs if x.model != type(self)]

它采用出_meta,这是不能保证是作为django的演变稳定的功能,但它确实特技并且可以在即时使用,如果需要的话。

原来,是我真正需要的是这样的:

模型继承与内容类型和继承感知管理器

这已经完全为我工作。感谢所有的人,虽然。我学到了很多东西只是读你的答案!

可以使用 django的多态性获得这一点。

它允许自动转换派生类回到它们的实际类型。它还提供Django管理支持,更高效的SQL查询处理,代理模型,内联和表单集支持。

的基本原理似乎是彻底改造多次(包括鸰的.specific,或在该交概述的实施例)。它需要更多的努力。然而,以确保它不会导致在N-查询问题,或者很好地与管理,表单集/内联或第三方应用程序集成。

下面是我的解决方案,它再次使用_meta所以不能保证稳定。

class Animal(models.model):
    name = models.CharField()
    number_legs = models.IntegerField()
    ...

    def get_child_animal(self):
        child_animal = None
        for r in self._meta.get_all_related_objects():
            if r.field.name == 'animal_ptr':
                child_animal = getattr(self, r.get_accessor_name())
        if not child_animal:
            raise Exception("No subclass, you shouldn't create Animals directly")
        return child_animal

class Dog(Animal):
    ...

for a in Animal.objects.all():
    a.get_child_animal() # returns the dog (or whatever) instance

您可以做到这一点寻找所有的父母是django.db.models.fields.related.RelatedManager的实例字段。从你的例子似乎你正在谈论的子类都没有子类。正确?

使用代理的另一种方法可以在此博客中找到帖子。像其他的解决方案,它有它的好处和责任,这是很好的放在后结束。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top