更改 Django 模型实例的多态内容类型

Change the polymorphic content type of a django model instance

如果我有一个多态模型:

class Father(polymorphic.model.PolymorphicModel)

和继承人 class 没有额外字段:

class Child(Father)

当我有 Father 实例时,如何将其转换为 Child 实例?

我试过的是:

foo = Father.objects.get(pk=1)
# foo is just a Father, no record in Child database table.
foo.polymorphic_ctype = ContentType.objects.get(app_label='myapp', model='child')
foo.save()

但没有任何变化。我希望 foo 成为一个子对象并且需要将其放入子数据库 table.

好的。

读完这篇类似的 post 我意识到我需要另一个作业:

foo.__class__ = Child

这会在子项中插入 table 否则永远不会发生。

Django 会自动将条目复制到父项中的子项中。对于创建 Child class 的迁移,您可以简单地将新的 Child 对象保存在数据库中(使用 __dict__ 属性 填充它们 python对象):

在迁移文件中定义此函数:

def duplicate_Children(apps,schema_editor):
    Father = apps.get_model('myapp','Father')
    Child= apps.get_model('myapp','Child')
    for dad in Father.objects.all():
         son = Child()

         for attr in dad.__dict__:
             son.__dict__[attr]=dad.__dict__[attr]

         son.save()

...

将此添加到迁移中的操作列表 class:

operations = [migrations.RunPython(duplicate_Children)]

对于多态模型你可以这样做:

kclass = YourChangeClass
# With that do the correct insert
self.__class__ = kclass
# With that change the correct model
ct = ContentType.objects.get_for_model(kclass)
self.polymorphic_ctype = ct
# With that set the default values
self.set_default_values()
self.save()

你需要为每个 class 定义一个定义默认值的方法,因为在其他情况下 save() 会失败!

例如,如果需要从A传递到B:

class A():
    attr_1
class B()
    attr_2
    def set_default_values(self):
        self.attr_2 = None