删除模型继承并在新创建的autofield中保留id

时间:2017-06-07 08:00:17

标签: python django postgresql inheritance django-migrations

我有一个继承自非抽象超级模型的模型:

class Person(models.Model):
    pass

class User(Person):
    pass

由于构思错误,我们希望删除Person模型并将所有人员数据复制到用户。主要问题涉及“id”AutoField。

用户模型没有任何由django自动处理的id字段。由于继承,用户的主键是“person_ptr_id”。

我正在尝试进行数据库迁移。 Django迁移想要将“id”字段添加为AutoField,但要求提供默认值。我想从person_ptr_id复制每个用户记录的初始值。 我还希望postgres序列与值同步。

您是否已经进行了此类迁移?

1 个答案:

答案 0 :(得分:0)

我终于成功完成了这些迁移:

1)通过注释person_ptr的列删除和'id'的列创建来更改django的自动迁移。然后将'id'列添加为整数:

migrations.AddField(
    model_name='user',
    name='id',
    field=models.IntegerField(null=True)
),

2)创建一个新的空迁移,用于将数据从人迁移到用户,删除person_ptr字段并将'id'类型更改为AutoField

def copy_persons_data(apps, schema_editor):
    User = apps.get_model("accounts", "User")
    Person = apps.get_model("persons", "Person")
    for user in User.objects.all():
        person = Person.objects.get(id=user.person_ptr_id)
        user.new_field1 = person.new_field1
        user.new_field2 = person.new_field2
        user.id = person.id
        user.save()

class Migration(migrations.Migration):

    dependencies = [
        ('accounts', '0026_auto_20170606_1524'),
    ]

    operations = [
        migrations.RunPython(copy_persons_data, reverse_code=migrations.RunPython.noop),
        migrations.RemoveField(
            model_name='user',
            name='person_ptr',
        ),
        migrations.AlterField(
            model_name='user',
            name='id',
            field=models.AutoField(auto_created=True, null=False, primary_key=True, serialize=False, verbose_name='ID'),
            preserve_default=False,
        ),
    ]

这样做,django将自动创建与id id同步的'id'字段的序列。

注意:

在datamigration函数中使用user.person_ptr将使django拒绝保存用户,因为未保存的人员实例。所以我做一个获取查询来获取用户的人员实例。

perserve_default = false非常重要,可以避免django需要新的迁移来删除autofield的默认值