模型继承 - 如何使用重写方法?

时间:2012-03-19 13:35:40

标签: django django-models

我有以下代码:

   # apps/models.py :

class Parent(models.Model):
    name = models.CharField(max_length=80)

    def __unicode__(self):
        clist = ", ".join([x.__unicode__() for x in self.children.all()])
        return self.name + clist

class Child(models.Model):  
    unit = models.ForeignKey(Parent, related_name='children')
    desc = models.CharField(max_length=80)

    def __unicode__(self):
         return self.desc

class ChildA(Child):
    text = models.TextField()

    def __unicode__(self):
         return self.text[:40]

我有几个ChildA类型的项目。为什么当我要求相关__unicode__()的{​​{1}}时,我得到的字符串是由Parent __unicode__()方法而不是Child生成的字符串。 } __unicode__()的方法?

更新

这是标准行为。除了以下答案之外,另一种可能的解决方案是inheritance cast

4 个答案:

答案 0 :(得分:5)

这是继承的标准行为。 ParentChild直接相关,而不是ChildA。当您致电some_parent.children.all()时,您会收到Child个实例的查询集,很明显,当您在其中一个实例上调用unicode时,它会调用Child.__unicode__

<强>更新

从父母到孩子,没有一个好方法。如果你正在使用MTI(多表继承),你可以利用Django实现它的方式,即与父进程OneToOneField。因此,孩子的父母也存在反向关系,但你必须专门测试它。例如:

class Child(models.Model):
    ...
    def get_child(self):
        if hasattr(self, 'childa'):
            return self.childa
        if hasattr(self, 'childb'):
            return self.childb
        ...

无论如何都不理想,每当你继承Child时,你总是需要小心总是更新这个方法,这几乎完全违反了OOP中的抽象。

答案 1 :(得分:0)

您可能想要一个抽象基类。

了解这里的差异...... https://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes

答案 2 :(得分:0)

  

为什么当我要求相关父级的 unicode ()字符串I时   get in return是由 unicode ()方法生成的   孩子?

因此,您没有在Parent实例上调用该方法。这就是你看到这种行为的原因。

答案 3 :(得分:0)

您可以使用super()关键字访问父类的方法:

a = ChildA()

#This will give you the normal method:
print unicode(a)

#super() will give you the parent's method:
super(ChildA, a).__unicode__()

您不能简单地将unicode()函数用于后一个调用,因为super会返回对象的代理,而不是单独的对象。

这不是一种好的代码方式。将它留给类来覆盖它认为合适的行为。