Django-变更迁移基础

mil*_*e_a 6 django

由于某些原因,我想对模型进行重大更改。我想以某种方式重做整个设计,但是Django迁移实现通过不更新模型库来牢记以前的设计。

让我快速展示一下我之前所拥有的,然后现在所拥有的。

app1.TopLevel
  |_ app1.IntermediateLevel
    |_ app2.LowLevel
Run Code Online (Sandbox Code Playgroud)

我有3个这样的模型,那么现在我想把这个设计切成更适合我当前项目的模型,例如

app2.TopLevel
  |_ app2.LowLevel
Run Code Online (Sandbox Code Playgroud)

我的主要更改是,首先,我不再需要中间模型,其次,我不需要顶部保持app1.TopLevel这种方式。

我的数据没有问题(我进行了多次迁移,有些是使用Python将数据放入临时字段中,然后稍后将数据放回到正确的字段中并删除那些临时字段)。

我的问题是,当我们创建继承的模型时,我们要定义其基础;

app1.TopLevel
  |_ app1.IntermediateLevel
    |_ app2.LowLevel
Run Code Online (Sandbox Code Playgroud)

在那种情况下,我会得到类似

类“ LowLevel”中的本地字段“ toplevel_ptr”与基类“ IntermediateLevel”中类似名称的字段发生冲突

我阅读了官方文档和源代码(用于迁移),但到目前为止,我什么都没有看到。是否可以告知迁移系统我们更改了模型库(其父库)?

否则,我唯一的解决方案是创建新模型,运行python迁移以将数据从旧模型复制到新模型。然后删除旧模型并重命名新模型,以获得我想要的名称。

And*_*bin 3

遇到了同样的问题bases,我最终编写了自己的迁移操作,如下所示。不过,值得一提的是,整个过程如下:

  1. 添加一个新的IntegerField模型null=True
  2. 将数据复制xxx_ptr到新字段
  3. 删除该xxx_ptr字段
  4. 运行RemoveModelBasesOptions操作
  5. 将临时 Integer 字段重命名为id并将其更改为AutoField
  6. 删除我继承的旧模型

需要注意的一件事是,如果您ForeignKey的模型有模型,它无论如何都会保留链接,所以它是安全的。

class RemoveModelBasesOptions(ModelOptionOperation):
    def __init__(self, name):
        super().__init__(name)

    def deconstruct(self):
        kwargs = {
            'name': self.name,
        }
        return (
            self.__class__.__qualname__,
            [],
            kwargs
        )

    def state_forwards(self, app_label, state):
        model_state = state.models[app_label, self.name_lower]
        model_state.bases = (models.Model,)
        state.reload_model(app_label, self.name_lower, delay=True)

    def database_forwards(self, app_label, schema_editor, from_state,
                          to_state):
        pass

    def database_backwards(self, app_label, schema_editor, from_state,
                           to_state):
        pass

    def describe(self):
        return "Remove bases from the model %s" % self.name

    @property
    def migration_name_fragment(self):
        return 'remove_%s_bases' % self.name_lower
Run Code Online (Sandbox Code Playgroud)

然后,只需将其作为迁移中的操作调用即可:

class Migration(migrations.Migration):
    dependencies = [
        ('xxxx', '0025_xxxx'),
    ]

    operations = [
        RemoveModelBasesOptions('Foo')
    ]
Run Code Online (Sandbox Code Playgroud)