Let’s say I have following ORM classes (fields removed to simplify):
class Animal(models.Model):
say = "?"
def say_something(self):
return self.say
class Cat(Animal):
self.say = "I'm a cat: miaow"
class Dog(Animal):
self.say = "I'm a dog: wuff"
class Animals(models.Model):
my_zoo = models.ManyToManyField("Animal")
When I add some animals to my zoo:
cat = Cat()
cat.save()
dog = Dog()
dog.save()
animals.my_zoo.add(cat)
animals.my_zoo.add(dog)
for animal in animals.my_zoo.all():
print animal.say_something()
… I would expect following result:
I’m a cat: miaow, I’m a dog: wuff
but instead, all I’ve got is the instances of general Animal object, unable to say anything but “?”.
How to achieve the true object inheritance and later polymorphism when the object is retreived from db?
Model inheritance in django does not add any type information to the base class. So it is not really possible to down-cast objects down from Animal() to their appropriate forms.
Inheritance is used only to map fields on inherited model back to parent models. So if Animal has field
name, the same field will exist onCatand when you saveCat, theanimalwill be updated.Inheritance works by adding a OneToOne relation:
Technically in your situation it is even possible for Animal() to be both Dog() and Cat() at the same time:
The way to solve your problem would be to add a field
subtypeor similar to yourAnimal()object and implement downcasting function:A few useful reads on stack overflow with similar topics:
Generic many-to-many relationships he hood.
How to do Inheritance Modeling in Relational Databases?