Django 1.8 迁移:有什么方法可以从不再有模型的数据库 table 中获取数据?

Django 1.8 migration: any way to get data from database table that no longer has a model?

我正在尝试重命名一个模型,我想以不依赖于在应用时仍然存在的旧名称的方式编写迁移。我能否以某种方式从迁移代码中不再具有模型的数据库 table 获取数据?

详情: 我有一个 Region 模型,我想将其移至更通用的 GeoObject 模型并从 models.py 中删除。如果我编写从现有 Regionsfrom models import Region 创建 GeoObjects 的迁移代码,我将必须保留 Region 模型,直到我的主数据库迁移。但我想编写一个迁移,以便它不依赖于存在的 Region 模型,只需检查数据库 table 是否存在并使用它。是否可以使用 Django instruments 来做到这一点,如果可能的话不依赖于特定的数据库类型?

是的,你可以。

但首先,你真的不应该在迁移中导入任何模型。

查看 RunPython 操作,这将允许您 运行 迁移中的任何 python 代码。 RunPython 将传递给您的函数 2 个参数:appsschema_editor。第一个参数包含应用该迁移阶段的模型结构,因此如果实际删除模型是在该迁移的后期,您仍然可以使用传递给函数的 apps 访问该模型。

假设您的模型如下所示:

class SomeModel(models.Model):
    some_field = models.CharField(max_length=32)

现在您要删除该模型,自动创建的迁移将包含:

class Migration(migrations.Migration):

    dependencies = [
        ('yourapp', '0001_initial'), # or any other dependencies
    ]

    operations = [
        migrations.DeleteModel(
            name='Main',
        ),
    ]

您可以通过在 DeleteModel 操作上方注入 RunPython 来修改该迁移:

    operations = [
        migrations.RunPython(
            move_data_to_other_model,
            move_data_back, # for backwards migration - if you won't ever want to undo this migration, just don't pass that function at all
        ),
        migrations.DeleteModel(
            name='SomeModel',
        ),
    ]

并在迁移前创建 2 个函数 class:

def move_data_to_other_model(apps, schema_editor):
    SomeModel = apps.get_model('yourapp', 'SomeModel')

    for something in SomeModel.objects.all():
        # do your data migration here
        o = OtherModel.objects.get(condition=True)
        o.other_field = something.some_field

def move_data_back(apps, schema_editor):
    SomeModel = apps.get_model('yourapp', 'SomeModel')

    for something in OtherModel.objects.all():
        # move back your data here
        SomeModel(
            some_field=something.other_field,
        ).save()

即使您的模型不再在 models.py 中定义也没关系,django 可以根据迁移历史重建该模型。但请记住:模型中的保存方法(和其他自定义方法)不会在迁移中被调用。此外,任何 pre_save 或 post_save 信号都不会被触发。