Python多态对象调用基类方法而不是子类方法

时间:2013-01-09 18:33:55

标签: python django polymorphism

我在Django中有以下模型。我有理由不让Animal成为抽象基类。

class Animal(models.Model):
    sound = "none"
    def ClassType(self):
        return 'animal'

class Cat(Animal):
    animal_id = models.OneToOneField(Animal,parent_link=True)
    sound = "meow"
    def ClassType(self):
        return 'cat'

class Dog(Animal):
    animal_id = models.OneToOneField(Animal,parent_link=True)
    sound = "bow"
    def ClassType(self):
        return 'dog'

我查询一组动物

query = Animal.objects.all()

结果是必须只有狗和猫的列表。但是,在致电

query[0].ClassType

我只得到animal。 “查询”中的所有对象都会给我animal,而我想根据实例获取dogcat。我在Python多态世界中没有理解什么?如何修复它?

3 个答案:

答案 0 :(得分:0)

您可以使用点表示法(如属性)访问dog和cat对象。查询Animal.objects.all()将返回包括所有猫和狗的所有动物。

qs = Animal.objects.all()
for animal in qs:
    try:
        obj = animal.cat
        # its a cat
    except AttrbuteError:
        # its a dog
        obj = animal.dog

如你所见,确定哪一只是狗,哪一只是猫,只是一个小故障,一个好的方法是在你的动物模型中设置一个临时属性:

class Animal(models.Model):
    sound = "none"

    def is_cat(self):
        if not hasattr(self, '_is_cat'):
            self._is_cat = Cat.objects.filter(animal_id=self).exists()
        return self._is_cat

现在你可以简单地做:

qs = Animal.objects.all()
for animal in qs:
    if animal.is_cat():
        # this is a cat
    else:
        # dog

答案 1 :(得分:0)

您应该将其设为实际字段,并在保存时存储对象的类型,而不是使ClassType成为方法。否则,正如您所发现的,当您查询动物时,您只会获得动物,而不是子类型。

答案 2 :(得分:0)

这个问题很老,但我遇到了同样的问题,所以这是我的解决方案:

我使用了django_polymorphic应用,由于多种原因它非常有用,但它提供了相应模型实例的属性及其名称,可用于解决问题。

因此,您可以将基类更改为如下所示:

class Animal(PolymorphicModel):
    sound = "none"

    def ClassType(self):
        polymorphic_attr_name = self.name.lower().replace(" ", "")  # Get the name of the attribute that points to the instance
        if polymorphic_attr_name == 'animal':
            return 'animal'
        instance = getattr(self, polymorphic_attr_name)
        return instance.ClassType()

然后你可以忘记任何动物亚类。它适用于我,希望这会有所帮助。