python - 将数据迁移作为大型 Django 迁移中的一项操作是否安全?

标签 python django

我正在处理我认为是一个常见问题:我已经意识到模型 Foo 的现有模型字段作为一个完全独立的模型 Bar 会更好带有指向 Foo 的外键。因此,我们需要进行模式迁移。但更重要的是,由于 Foo 的模型字段中已经存在数据,因此我们需要在删除该字段之前进行数据迁移。

因此,我们确定需要采取三个不同的步骤:

  1. 创建新表条形图
  2. Foo 中的现有数据迁移到新表 Bar
  3. 删除Foo中已有的字段

首先,我在 models.py 中进行所有需要的模型更改,然后自动生成迁移。一切看起来都不错,除了我们将丢失该字段中的所有数据,所以我需要添加一个额外的 operation处理数据迁移( RunPython) 。我最终会得到如下内容:

def do_data_migration(apps, schema_editor):
    # Migrate data from Foo to Bar

class Migration(migrations.Migration):

    dependencies = [ 
        ('exampleapp', 'migration_003'),
    ]   

    operations = [ 
        migrations.CreateModel(
            # Create the new model Bar
        ),  
        migrations.AddField(
            # Add the foreign key field to model Foo
        ),  
        migrations.RunPython(
            do_data_migration
        ),
        migrations.RemoveField(
            # Remove the old field from Foo
        ),  
    ]

将数据迁移作为迁移中的多个操作之一运行是否安全?我担心的是是否正在进行任何类型的锁定,或者 RunPython 传递给 do_data_migration 的应用程序注册表可能不会与前面的操作保持同步?

我知道我可以创建三个迁移:一个用于 CreateModelAddField,第二个用于 RunPython,最后一个用于 删除字段。问题是在单个迁​​移中执行所有四个步骤在功能上是否等效(这提供了使整个迁移更易于理解的额外好处。)

最佳答案

对于 Django 本身,这是绝对安全的。每个操作都将根据所有先前的迁移和同一迁移中的操作接收正确的状态。您的 RunPython 操作将收到一个应用注册表,其中包含新的 Bar 模型,并且在 Foo 上仍有旧字段。

可能不安全的是操作的数据库端。如果数据库在事务中支持 DDL(数据定义语言),Django 将在单个事务中运行完整的迁移。例如,PostgreSQL 支持事务中的 DDL,但不允许您在同一事务中混合模式更改和数据更改。尝试在单个迁移/事务中执行这两项操作将导致错误。

如果您使用不支持 DDL 事务并且只会在事务中运行 RunPython 操作的 MySQL 或 Oracle,您可以安全地将所有操作放在同一个迁移中。但是,您将失去一些跨数据库兼容性。

关于python - 将数据迁移作为大型 Django 迁移中的一项操作是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38023545/

相关文章:

python - 无法在 redshift 中的表上写入

python - 设计启发式方法来编写与 `scipy.integrate.odeint` 交互的 Python 类?

database - 我应该在事务中包含 SELECTs 吗?

django - 如何在模板中调用模型方法

python - Flask-Uploads URL 始终是 404

python - 当我尝试执行sql查询时出现错误

python - 如何使用 python evdev 访问游戏 handle 的操纵杆?

django - 在多容器 Docker 设置中运行 Django 迁移

django - 将 KML 转换为 Postgis- Django/Python

django - 我可以为 Django 测试设置一个数据库吗?