我有以下代码:
# 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
答案 0 :(得分:5)
这是继承的标准行为。 Parent
与Child
直接相关,而不是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
会返回对象的代理,而不是单独的对象。
这不是一种好的代码方式。将它留给类来覆盖它认为合适的行为。