Django模型继承:使用现有超类创建子类

Posted

技术标签:

【中文标题】Django模型继承:使用现有超类创建子类【英文标题】:Django model inheritance: Create a subclass using existing super class 【发布时间】:2012-04-06 23:51:16 【问题描述】:

我正在使用multi-table-inheritance,并且想知道如何从超类的实例创建继承类型。

使用文档中给出的示例:

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField()
    serves_pizza = models.BooleanField()

现在,当您创建 Restaurant 时,您会自动创建 Place,这很好,也是我期望和想要的行为。

但是如果我创建了一个Place,然后决定我想转换为一个特定的类型(比如Restaurant)。如何使用现有的Place 创建Restaurant

【问题讨论】:

Django model inheritance: create sub-instance of existing instance (downcast)?的可能重复 我看到了那个问题和答案,但很困惑,因为我认为这个问题与身份验证有关(因为 User 更像是一个特殊对象) 我赞成您的重复言论,但是...所指的问题是关于用户的,这可能会令人困惑。我发现这个地方和餐馆的例子(从 Django 文档中偷来的)更清楚,更类似于我的问题....但在基础上它是同样的问题。 见code.djangoproject.com/ticket/7623 【参考方案1】:

虽然没有记录,但这似乎可以解决问题:

restaurant(place_ptr=place).save_base(raw=True)

这在不使用任何技巧的情况下解决了问题,并且在处理方面也是最短的解决方案,使用 Django API。

在搜索此解决方案时,我还找到了一个稍长的解决方案,但使用了文档化的 API。与Mariusz answer基本相同,详情见this answer:

from django.forms.models import model_to_dict

restaurant(place_ptr=place, **model_to_dict(place)).save()

但是,由于 model_to_dict 返回的字段集有限,第二个风险更大(再次查看解释所呈现的各种方法之间差异的答案)。自然,它还会生成更多的 DB 调用,因为它写入两个表。

【讨论】:

【参考方案2】:
place = Place.objects.get(id=1)

# Create a restaurant using existing Place
place.__class__ = Restaurant
place.save()
restaurant = place

【讨论】:

【参考方案3】:

多表继承只是Place 和Restaurant 之间的OneToOneField 关系。

place = Place.objects.get(id=1)               

# Create a restaurant using existing Place   
restaurant = Resturant(place_ptr=place)
restaurant.save()

【讨论】:

这将导致 restaurant.name 被清空。因为 restaurant.save() 会用 name='' 更新 Place(因为 restaurant = Resturant())...一定有更好的方法... 你应该添加 restaurant.__dict__.update(place.__dict__),见Daniel Roseman's answer。 好的,结合 secator 的答案和 jpic 的添加就可以了...

以上是关于Django模型继承:使用现有超类创建子类的主要内容,如果未能解决你的问题,请参考以下文章

无法从超类访问 Django 模型的子类

使用 Django Model 类继承为表创建审计日志

Django,Python继承:从超类中排除一些字段

Java 中的继承——创建子类的对象也会调用超类的构造函数。为啥?

python类的继承

解码子类时忽略超类属性