我有一个真实的案例,可以使用像Java
中的多态来解决我们可以在哪里创建属于同一类型的对象列表。但是,每个对象可能具有覆盖或额外字段。
class Animal(models.Model):
name = models.CharField(max_length=30)
def speak(self):
return "I am an animal"
class Cat(Animal):
def speak(self):
""" OVERRIDE """
return "MEAOO"
class Dog(Animal):
def speak(self):
""" OVERRIDE """
return "WOOOOF"
我现在需要的是获得所有动物,但让每只动物使用它的说话方法。我无法如下所示。
>>> c = Cat(name="MyCAT")
>>> c.save()
>>> d = Dog(name="MyDOG")
>>> d.save()
>>> animals = Animal.objects.all()
>>> animals
[<Animal: Animal object>, <Animal: Animal object>]
>>> for a in animals:
... a.speak()
...
'I am an animal'
'I am an animal'
>>>
对我而言,输出应该如下所示
'MEAOO'
'WOOOOF'
有没有在Django做类似的事情?
答案 0 :(得分:1)
我最近遇到了这个问题。我有几个子类,而且所有子类都略有不同&#34;说&#34;方法
我基本上做的是在我的父类中创建一个downcast
函数,它检查相关的子类实例。这是有效的,因为当您将模型子类化时,django通过OneToOneField
链接它们,这可以通过两种方式遍历:
class Animal(models.Model):
name = models.CharField(max_length=30)
_downcast = None
# to store the subclass instance, so that
# subsequent calls don't hit the database
def speak(self):
return "I am an animal"
def downcast(self):
if self._downcast is None:
if hasattr(self, 'cat'):
self._downcast = self.cat
elif hasattr(self, 'dog'):
self._downcast = self.dog
return self._downcast
class Cat(Animal):
def speak(self):
""" OVERRIDE """
return "MEAOO"
class Dog(Animal):
def speak(self):
""" OVERRIDE """
return "WOOOOF"
基本上,你只是...有点......去找它,并问你的数据库这个Animal
是否确实有一个相关的Cat
行:
>>> a = Animal.objects.all().first() #let's assume this is a cat
>>> a.speak()
I am an animal
>>> a.downcast().speak()
MEAOO
当然,这会查询数据库,因此性能可能会受到影响。考虑一下您自己的场景并运行一些测试,看看这是否适合您。