migrations - django恢复上次迁移




django数据迁移 (5)

我已经进行了迁移,添加了一个新表,并希望还原它并删除迁移,而不创建新的迁移。

我该怎么做? 是否有恢复上次迁移的命令,然后我可以删除迁移文件?

https://code.i-harness.com


Alasdair的答案涵盖了基础知识

  • 通过 ./manage.py showmigrations 确定所需的迁移
  • 使用应用名称和迁移名称进行迁移

但应该指出的是,并非所有迁移 可以逆转。 如果Django没有规则来进行逆转,就会发生这种情况。 对于您通过 ./manage.py makemigrations 自动进行迁移的大多数更改,可以进行反转。 但是,自定义脚本需要同时写入正向和反向,如下例所示:

https://docs.djangoproject.com/en/1.9/ref/migration-operations/

如何进行无操作逆转

如果您有 RunPython 操作,那么您可能只想退出迁移而不编写逻辑上严格的反转脚本。 以下对文档示例的快速入侵(上面的链接)允许这样做,使数据库处于迁移应用后的状态,即使在撤消之后也是如此。

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

def forwards_func(apps, schema_editor):
    # We get the model from the versioned app registry;
    # if we directly import it, it'll be the wrong version
    Country = apps.get_model("myapp", "Country")
    db_alias = schema_editor.connection.alias
    Country.objects.using(db_alias).bulk_create([
        Country(name="USA", code="us"),
        Country(name="France", code="fr"),
    ])

class Migration(migrations.Migration):

    dependencies = []

    operations = [
        migrations.RunPython(forwards_func, lambda apps, schema_editor: None),
    ]

这适用于Django 1.8,1.9

更新:更好的方法是在上面的代码片段中使用 migrations.RunPython.noop 替换 lambda apps, schema_editor: None 。 这些在功能上都是一样的。 (信用评论)


如果您在恢复迁移时遇到问题,并且以某种方式弄乱了它,则可以执行 fake 迁移。

./manage.py migrate <name> --ignore-ghost-migrations --merge --fake

对于 django version <1.7, 这将在 south_migrationhistory 表中创建条目,您需要删除该条目。

现在,您将能够轻松恢复迁移。

PS:我被困了很长时间并进行虚假迁移然后回复帮助了我。


您可以通过迁移到先前的迁移来恢复。

例如,如果您的最后两次迁移是:

  • 0010_previous_migration
  • 0011_migration_to_revert

然后你会做:

./manage.py migrate my_app 0010_previous_migration 

然后,您可以删除迁移 0011_migration_to_revert

如果您使用的是Django 1.8+,则可以显示所有迁移的名称

./manage.py showmigrations my_app

要撤消应用的所有迁移,您可以运行:

./manage.py migrate my_app zero

我在1.9.1中做了这个(删除创建的最后一个或最新的迁移):

  1. rm <appname>/migrations/<migration #>*

    示例: rm myapp/migrations/0011*

  2. 登录到数据库并运行此SQL(在此示例中为postgres)

    delete from django_migrations where name like '0011%';

然后我能够创建以我刚刚删除的迁移号码开始的新迁移(在本例中为11)。


如果Alasdair的最佳答案没有帮助, 这个答案适用于类似案例。 (例如,如果每次新迁移都会立即再次创建不需要的迁移,或者如果它处于无法恢复的较大迁移中,或者手动删除了表。)

...删除迁移,而不创建新的迁移?

TL; DR :您可以删除一些最后恢复(混乱)的迁移,并 在修复模型后 创建一个新的迁移。 您还可以 使用其他方法 将其配置 为不 通过migrate命令 创建表 必须创建上次迁移,以使其与当前模型匹配

为什么有人不想为必须存在的模型创建表的情况:

A) 在没有机器和没有条件的数据库中不存在这样的表

  • 时间: 它是仅为其他模型的模型继承创建的基本模型。
  • 解决方案: 设置 class Meta: abstract = True

B) 该表很少通过其他方式创建或以特殊方式手动创建。

  • 解决方案: 使用 class Meta: managed = False
    迁移已创建,但从未在测试中使用过。 迁移文件很重要,否则数据库测试无法运行,从可重现的初始状态开始。

C) 该表仅用于某些机器(例如,在开发中)。

  • 解决方案: 将模型移动到仅在特殊条件下添加到INSTALLED_APPS的新应用程序,或使用条件 class Meta: managed = some_switch

D) 项目在 settings.DATABASES 使用多个数据库

  • 解决方案: 使用方法 allow_migrate 编写 数据库路由器 ,以区分应创建表的数据库和不应创建表的数据库。

在所有情况下,使用Django 1.9+创建迁移A),B),C),D)(仅在B,C,D和Django 1.8的情况下),但仅在适当情况下应用于数据库,或者可能永远不会要求如此。 自Django 1.8以来,迁移是运行测试所必需的。 即使对于Django 1.9+中具有managed = False的模型,迁移也可以记录完整的相关当前状态,以便可以在托管/非托管模型之间创建ForeignKey,或者可以使模型托管= True。 (这个问题是在Django 1.8时编写的。这里的所有内容都适用于1.8到2.2之间的版本。)

如果上次迁移不易 恢复 ,则可以谨慎(在数据库备份之后)执行 虚假还原 ./manage.py migrate --fake my_app 0010_previous_migration ,手动删除表。

如有必要,从固定模型创建固定迁移并应用它而不更改数据库结构 ./manage.py migrate --fake my_app 0011_fixed_migration







django-migrations