Answers:
您可以通过迁移到上一个迁移来还原。
例如,如果您的最后两个迁移是:
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
'0010_previous_migration'
,我不知道您为什么会看到这种行为。
Alasdair的答案涵盖了基础知识
./manage.py showmigrations
migrate
使用应用名称和迁移名称但是应该指出,并非所有迁移都可以逆转。如果Django没有规则进行逆转,则会发生这种情况。对于您通过进行自动迁移的大多数更改,./manage.py makemigrations
都可以撤消。但是,自定义脚本将需要同时编写正向和反向脚本,如此处的示例所述:
https://docs.djangoproject.com/zh-CN/1.9/ref/migration-operations/
如果您有一项RunPython
操作,那么也许您只是想在不编写逻辑上严格的反向脚本的情况下取消迁移。以下来自docs(上链接)的示例的快速介绍允许这样做,即使恢复后,数据库仍保持与应用迁移后相同的状态。
# -*- 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
更新:编写此代码的更好方法是在上面的代码段中替换lambda apps, schema_editor: None
为migrations.RunPython.noop
。这些在功能上都是相同的。(记入评论)
RunPython.noop
而不是内联lambda或等价的:docs.djangoproject.com/en/1.8/ref/migration-operations/…–
migrations.RunPython(forwards_func, migrations.RunPython.noop)
。需要进行功能检查。有时应该将其添加为对此的答案或编辑。
这是我的解决方案,因为当您使用时上述解决方案并没有真正涵盖用例RunPython
。
您可以通过ORM通过访问表
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访问表。
django.db.utils.ProgrammingError: relation "<relation name>" already exists
这样的错误消息,所以我做了一个错误的消息migrate --fake
,所以我尝试回去,然后得到了psycopg2.ProgrammingError: relation "<other <relation name>" does not exist
感谢
您可以做的另一件事是删除手动创建的表。
除此之外,您还必须删除该特定的迁移文件。另外,您将必须删除与该特定迁移相关的django-migrations表中的特定条目(在您的情况下可能是最后一个)。
我在1.9.1中做到了这一点(删除了上一次创建的迁移或最新创建的迁移):
rm <appname>/migrations/<migration #>*
例: rm myapp/migrations/0011*
登录数据库并运行此SQL(在此示例中为postgres)
delete from django_migrations where name like '0011%';
然后,我可以创建新的迁移,该迁移以我刚刚删除的迁移号(在本例中为11)开头。
如果Alasdair的最高答案无济于事,则此答案适用于类似情况。(例如,如果在每次新迁移时很快又创建了不想要的迁移,或者该迁移处于无法还原的较大迁移中,或者手动删除了该表。)
...删除迁移,而不创建新的迁移?
TL; DR:您可以删除一些最近恢复的(混淆的)迁移,并在修复模型后进行新的迁移。您还可以使用其他方法将其配置为不通过migration命令创建表。必须创建最后一个迁移,以使其与当前模型匹配。
案例为什么有人不想创建一个表必须存在一个型号:
A)这样的表应该不存在于没有机器,没有条件的数据库中
class Meta: abstract = True
B)很少通过其他方式或以特殊方式手动创建表。
class Meta: managed = False
C)该表仅在某些机器上使用(例如,正在开发中)。
class Meta: managed = some_switch
。D)项目使用多个数据库settings.DATABASES
allow_migrate
以区分应在何处创建表的数据库以及应在何处创建表的数据库。迁移是在Django 1.9+的所有情况A),B),C),D)中创建的(并且仅在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
迁移。
./manage.py migrate <name> --ignore-ghost-migrations --merge --fake
对于django版本<1.7,它将在south_migrationhistory
表中创建条目,您需要删除该条目。
现在,您将能够轻松地还原迁移。
PS:我被困了很多时间,进行了虚假的迁移,然后恢复原状帮助了我。