Django ORM继承ManyToMany字段 [英] Django ORM inheritance with ManyToMany field

查看:143
本文介绍了Django ORM继承ManyToMany字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下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字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆