创建新字段后无法使用 RunPython 在迁移中获取模型记录

时间:2021-05-11 10:00:43

标签: python django web

问题:

  1. 我在我的模型 MyModel 中创建了一个名为“new_field”的新字段,创建了添加此字段的迁移“01”。之后,我想在新迁移“02
  2. 中更改某些旧字段“old_field”的模型记录
  3. 所以我创建了迁移 "02",它使用 RunPython 更改了我的记录,它可能如下所示:

.

from ..models import MyModel

def update_model():
     for record in MyModel.objects.all():
        record.new_field = record.old_field
        record.save()

class Migration(migrations.Migration):
        dependencies = [('myapp', '01')]
        operation = [migrations.RunPython(update_model, lambda *args: None)]

此迁移将运行良好,但之后我想创建新字段“super_new_field”:

  1. 我正在创建迁移“03”,它会创建新字段“super_new_field

一切都会好的。但是如果我清除数据库然后运行迁移,迁移“02”将不起作用,因为它试图访问在 Django 中确实有字段“super_new_field”的 MyModel,但是由于尚未执行迁移“03”,因此数据库中仍然缺少它。 这意味着必须删除“def update_model”中的这段代码(或必须更改迁移顺序和其他所有内容)才能在新环境中执行迁移,这并不好

问题:

有没有办法在迁移中更新模型记录并避免这个问题?迁移似乎是一个不错的地方,因为我需要在执行迁移后只更新一次记录,但是如果我要创建新字段和迁移,那么之前尝试访问模型记录的迁移将不起作用,因为缺少字段.

1 个答案:

答案 0 :(得分:2)

关于数据迁移的documentation描述了我们需要在迁移过程中使用历史模型,因为直接导入的模型可能比预期的版本通过迁移。 RunPython 将两个参数 appsschema_editor 传递给被调用的函数。其中,我们可以使用 apps 来获取历史模型:

def update_model(apps, schema_editor):
     MyModel= apps.get_model('yourappname', 'MyModel')
     for record in MyModel.objects.all():
        record.new_field = record.old_field
        record.save()

class Migration(migrations.Migration):
        dependencies = [('myapp', '01')]
        # Don't use `lambda *args: None` just pass `RunPython.noop` instead
        operation = [migrations.RunPython(update_model, migrations.RunPython.noop)]
相关问题