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

Posted

技术标签:

【中文标题】Django 1.8 迁移:有啥方法可以从不再有模型的数据库表中获取数据?【英文标题】:Django 1.8 migration: any way to get data from database table that no longer has a model?Django 1.8 迁移:有什么方法可以从不再有模型的数据库表中获取数据? 【发布时间】:2015-11-19 04:13:19 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:

是的,你可以。

但首先,您确实不应该在迁移中导入任何模型。

查看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 个函数:

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 信号。

【讨论】:

谢谢,感谢您的努力,但我如何编写代码来在迁移中创建新实例?是的,我已经在使用RunPython,而且我什至不知道其他方法,有吗?无论如何,问题是我还不知道如何访问没有模型的数据库表。我已经从models.py 中删除了模型。我将通过链接重新检查文档,谢谢。 apps 传入你的函数并不依赖于你的models.py。这取决于迁移历史。该模型状态是由已经执行的迁移操作构建的,因此如果从数据库中删除模型的操作稍后在迁移中进行,则该模型仍可使用apps。查看更新的答案。 完美。非常感谢。

以上是关于Django 1.8 迁移:有啥方法可以从不再有模型的数据库表中获取数据?的主要内容,如果未能解决你的问题,请参考以下文章

将旧 (Django 0.97) 模型数据导入/迁移到 Django 1.8 或更高版本

我如何为 django 1.8 编写初始数据

使用 --fake 后如何在 django 1.8 上重做迁移

Django 1.8 - migrate 和 makemigrations 有啥区别?

无法将 Django 从 1.7 迁移到 1.8

django 1.8 测试模型和迁移