django恢复上次迁移

django revert last migration

我进行了一次迁移,添加了一个新表,希望在不创建新迁移的情况下还原它并删除迁移。

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


您可以通过迁移到上一个迁移来还原。

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

  • 0010_previous_migration
  • 江户十一〔一〕号
  • 小精灵

    然后你会做:

    1
    ./manage.py migrate my_app 0010_previous_migration

    然后可以删除迁移0011_migration_to_revert

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

    1
    ./manage.py showmigrations my_app

    要反转应用程序的所有迁移,可以运行:

    1
    ./manage.py migrate my_app zero


    Alasdair的答案涵盖了基础知识

    • 确定./manage.py showmigrations想要的迁移
    • migrate使用app名称和迁移名称
    • 小精灵

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

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

      如何进行无操作反转

      如果您有一个RunPython操作,那么您可能只是想退出迁移,而不编写逻辑上严格的反转脚本。下面从docs(上面的链接)对示例进行的快速黑客攻击允许这样做,使数据库处于应用迁移之后的相同状态,即使是在反向迁移之后。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      # -*- 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。它们在功能上是相同的。(归功于评论)


      您可以做的另一件事是删除手动创建的表。

      除此之外,您还必须删除特定的迁移文件。此外,您还必须删除django migrations表中与特定迁移相关的特定条目(可能是您案例中的最后一个条目)。


      这是我的解决方案,因为当您使用RunPython时,上面的解决方案并不真正涵盖用例。

      您可以通过ORM访问表

      1
      2
      3
      4
      5
      6
      7
      from django.db.migrations.recorder import MigrationRecorder

      >>> MigrationRecorder.Migration.objects.all()
      >>> MigrationRecorder.Migration.objects.latest('id')
      Out[5]: <Migration: Migration 0050_auto_20170603_1814 for model>
      >>> MigrationRecorder.Migration.objects.latest('id').delete()
      Out[4]: (1, {u'migrations.Migration': 1})

      因此,您可以查询表并删除那些与您相关的条目。这样您可以详细修改。对于RynPython迁移,您还需要处理添加/更改/删除的数据。上面的示例仅显示如何通过DJANG ORM访问表。


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

    • 埃多克斯1〔9〕

      示例:rm myapp/migrations/0011*

    • 登录数据库并运行此SQL(本例中为Postgres)

      江户十一〔11〕。

    • 然后我可以创建新的迁移,从我刚删除的迁移编号开始(在本例中是11)。


      如果Alasdair给出的最高答案没有帮助,那么这个答案也适用于类似的情况。(例如,如果不需要的迁移在每次新迁移后很快又被创建,或者如果它处于无法恢复的更大迁移中,或者表已被手动删除。)

      ...delete the migration, without creating a new migration?

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

      任何人不想为必须存在的模型创建表的情况:

      a)在没有机器和条件的数据库中不应该存在这样的表。

      • 当:它是只为其他模型的模型继承而创建的基础模型。
      • 解决方案:设置EDOCX1[0]
      • 小精灵

        b)表很少由其他东西或以特殊方式手动创建。

        • 解决方案:使用EDOCX1[1]只在测试中创建迁移,但从不使用迁移。迁移文件很重要,否则数据库测试无法运行,从可重复的初始状态开始。
        • 小精灵

          c)工作台仅在某些机器上使用(例如在开发中)。

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

            d)该项目在settings.DATABASES中使用多个数据库。

            • 解决方案:用allow_migrate方法编写一个数据库路由器,以区分应该在哪里创建表,在哪里不创建表。
            • 小精灵

              迁移在所有情况下都是使用django 1.9+创建的(并且仅在使用django 1.8创建的情况下使用b、c、d),但仅在适当情况下应用于数据库,或者在需要时从未应用于数据库。自Django 1.8以来,迁移是运行测试所必需的。迁移会记录完整的相关当前状态,即使对于django 1.9+中managed=false的模型,也可以在托管/非托管模型之间创建foreignkey,或者稍后将模型设置为managed=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的情况下应用它。


              如果您在恢复迁移的过程中遇到问题,并且不知何故造成了混乱,则可以执行fake迁移。

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

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

              现在您可以轻松地恢复迁移。

              附言:我被困了很多时间,执行假迁移,然后恢复回来帮助了我。