Model inheritance. How to use overridden methods?
I have the following code:
# 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]
I have several elements of type ChildA
. Why, when I ask for the __unicode__()
appropriate Parent
, is the string I get in return the one generated by the method __unicode__()
Child
and not the method __unicode__()
ChildA
?
Update:
This is standard behavior. Other possible solutions in addition to below answers are inheritance inheritance
source to share
This is the standard behavior for inheritance. Parent
is directly related to Child
, not ChildA
. When you call some_parent.children.all()
, you return a set of instance requests Child
, so obviously when you call unicode
on one of them, it calls Child.__unicode__
.
UPDATE
There's not a very good way to get from parent to child. If you are using MTI (Multiple Table Inheritance), you can take advantage of the way Django implements it, namely as OneToOneField
a parent. There is also parent-child feedback because of this, but you must specifically test it. For example:
class Child(models.Model):
...
def get_child(self):
if hasattr(self, 'childa'):
return self.childa
if hasattr(self, 'childb'):
return self.childb
...
This is not ideal and you need to be careful to always update this method whenever you subclass Child
, which pretty much completely breaks abstraction in OOP.
source to share
You probably want an abstract base class.
Read the difference here ... https://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes
source to share
You can access the parent class method using the keyword super()
:
a = ChildA()
#This will give you the normal method:
print unicode(a)
#super() will give you the parent method:
super(ChildA, a).__unicode__()
You cannot just use the function unicode()
with the last call, as it super
returns a proxy for the object, not a native object.
This is not the best way to code. Leave it up to the class to override the behavior as you see fit.
source to share