问题描述
假设我有以下ORM类(字段被删除以简化): class Animal(models.Model):
say =?
def say_something(self):
return self.say
class Cat(Animal):
self.say =我是一只猫:miaow
class Dog(Animal):
self.say =我是一只狗:wuff
class动物(models.Model):
my_zoo = models.ManyToManyField(Animal)
当我将一些动物添加到我的动物园:
cat = Cat()
cat.save()
dog = b $ b dog.save()
animals.my_zoo.add(cat)
animals.my_zoo.add(dog)
for animals.my_zoo .all():
print animal.say_something()
...我期望以下结果:
我是一只猫:miaow,我是一只狗:wuff
我所有的都是一般Animal对象的实例,除了?之外不能说任何东西。
如何实现真正的对象继承和以后的多态对象从数据库中获取?
在django中的模型继承不会向基类添加任何类型的信息。所以它不是真的可以将对象从Animal()下降到适当的形式。
继承仅用于将继承的模型上的字段映射回父模型。所以如果Animal有一个字段 name
,那么相同的字段将存在于 Cat
上,当你保存猫
,动物
将被更新。
继承通过添加OneToOne关系:
$ b
class Animal(Model):
name = CharField()
class Cat (模型):
animal_ptr = OneToOneField(动物)
Cat(name ='Murky')。save()
print repr(list(Animals.objects .all()))
:[Animal(name ='Murky')]
在您的情况下,Animal()可以同时兼容Dog()和Cat():
animal = Animal()
animal.save()
猫(animal_ptr =动物).save()
狗(animal_ptr =动物).save )
解决问题的方法是添加一个字段 subtype
或类似于您的 Animal()
对象并实现下载功能:
class Animal(Model):
subtype = CharField()
def downcast(self):
if self。 subtype =='cat':
return self.cat
#self.cat是一个自动反向引用,从OneToOne字段创建
#,名称为
$ b动物的$ b为Animal.objects.all()。select_related('dog','cat',...)]:
animal.downcast()。say_something()
堆栈溢出的一些有用的读取类似主题:
他的引导。
如何在关系数据库中进行继承建模?
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 on Cat
and when you save Cat
, the animal
will be updated.
Inheritance works by adding a OneToOne relation:
class Animal(Model):
name = CharField()
class Cat(Model):
animal_ptr = OneToOneField(Animal)
Cat(name='Murky').save()
print repr(list(Animals.objects.all()))
: [Animal(name='Murky')]
Technically in your situation it is even possible for Animal() to be both Dog() and Cat() at the same time:
animal = Animal()
animal.save()
Cat(animal_ptr=animal).save()
Dog(animal_ptr=animal).save()
The way to solve your problem would be to add a field subtype
or similar to your Animal()
object and implement downcasting function:
class Animal(Model):
subtype = CharField()
def downcast(self):
if self.subtype == 'cat':
return self.cat
# The self.cat is a automatic reverse reference created
# from OneToOne field with the name of the model
for animal in Animal.objects.all().select_related('dog', 'cat', ...)]:
animal.downcast().say_something()
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?
这篇关于Django ORM继承ManyToMany字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!