我在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
,而我想根据实例获取dog
或cat
。我在Python多态世界中没有理解什么?如何修复它?
答案 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()
然后你可以忘记任何动物亚类。它适用于我,希望这会有所帮助。