我做了一个迁移,添加了一个新表,想要恢复它并删除迁移,而不创建一个新的迁移。
我该怎么做?是否有恢复上次迁移的命令,然后我可以简单地删除迁移文件?
我做了一个迁移,添加了一个新表,想要恢复它并删除迁移,而不创建一个新的迁移。
我该怎么做?是否有恢复上次迁移的命令,然后我可以简单地删除迁移文件?
您可以通过迁移到以前的迁移进行恢复。
例如,如果你的最后两次迁移是:
0010年_previous_migration 0011年_migration_to_revert
然后你会这样做:
./manage.py migrate my_app 0010_previous_migration
您实际上不需要使用完整的迁移名称,数量就足够了,即。
./manage.py migrate my_app 0010
然后可以删除迁移0011_migration_to_revert。
如果你使用的是Django 1.8+,你可以显示所有迁移的名称
./manage.py showmigrations my_app
要反转应用程序的所有迁移,你可以运行:
./manage.py migrate my_app zero
您可以做的另一件事是删除手动创建的表。
与此同时,您还必须删除特定的迁移文件。同时,你必须删除django-migrations表中与特定迁移相关的特定条目(可能是你的情况下的最后一个)。
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
更新:更好的编写方法是将上面代码片段中的lambda apps, schema_editor: None替换为migrations.RunPython.noop。它们在功能上是一样的。(来源:评论)
我在1.9.1中这样做了(删除最后或最新创建的迁移):
Rm <appname>/migrations/<migration #>* .使用实例 例如:rm myapp/migrations/0011* 登录到数据库并运行SQL语句(本例中为postgres) 删除django_migrations中名称为“0011%”的位置;
然后,我可以创建新的迁移,以刚才删除的迁移编号(在本例中为11)开始。
下面是我的解决方案,因为上面的解决方案并没有真正涵盖使用RunPython时的用例。
可以通过ORM with访问该表
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访问表。
这个答案适用于类似的情况,如果Alasdair给出的最上面的答案没有帮助。(例如,如果不需要的迁移很快在每次新的迁移中再次创建,或者如果它是在一个更大的迁移中,不能恢复,或者表已经被手动删除。)
删除迁移,而不创建新的迁移?
TL;DR:您可以删除一些最后恢复的(混乱的)迁移,并在修复模型后进行一个新的迁移。您还可以使用其他方法将其配置为不通过migrate命令创建表。必须创建最后一个迁移,以便与当前模型匹配。
为什么任何人都不想为必须存在的模型创建表:
A)在任何机器、任何数据库和任何条件下都不应该存在这样的表
当:仅为继承其他模型而创建的基础模型。 解决方法:设置类Meta: abstract = True
B)该表很少创建,由其他东西或手动以特殊方式创建。
解决方案:使用类Meta: managed = False 迁移已经创建,但从未使用,仅在测试中使用。迁移文件很重要,否则数据库测试无法从可重现的初始状态开始运行。
C)该表只在某些机器上使用(例如在开发中)。
解决方案:将模型移动到仅在特殊条件下才添加到INSTALLED_APPS的新应用程序中,或者使用条件类Meta: managed = some_switch。
D)该项目在设置中使用多个数据库。数据库
解决方案:使用allow_migrate方法编写一个数据库路由器,以便区分应该在哪里创建表和不应该在哪里创建表的数据库。
The migration is created in all cases A), B), C), D) with Django 1.9+ (and only in cases B, C, D with Django 1.8), but applied to the database only in appropriate cases or maybe never if required so. Migrations have been necessary for running tests since Django 1.8. The complete relevant current state is recorded by migrations even for models with managed=False in Django 1.9+ to be possible to create a ForeignKey between managed/unmanaged models or to can make the model managed=True later. (This question has been written at the time of Django 1.8. Everything here should be valid for versions between 1.8 to the current 2.2.)
如果最后一次迁移(are)不容易可逆,那么可以谨慎地(在数据库备份后)做一个假恢复。/manage.py migrate——fake my_app 0010_previous_migration,手动删除表。
如果有必要,从固定的模型创建一个固定的迁移,并在不改变数据库结构的情况下应用它。
如果您在恢复迁移时遇到了麻烦,并且在某种程度上搞砸了它,那么您可以执行假迁移。
./manage.py migrate <name> --ignore-ghost-migrations --merge --fake
对于django版本小于1.7的版本,这将在south_migrationhistory表中创建条目,你需要删除该条目。
现在您可以轻松地恢复迁移。
PS:我被困了很长时间,执行假迁移,然后返回帮助我解决了问题。
在恢复之前不要删除迁移文件。我犯了这个错误,没有迁移文件,数据库就不知道要删除什么东西。
python manage.py showmigrations
python manage.py migrate {app name from show migrations} {00##_migration file.py}
如果你想恢复所有的迁移,使用0作为迁移的名称:
python manage.py migrate app_name_here zero
删除迁移文件。一旦您的模型中有了所需的迁移……
python manage.py makemigrations
python manage.py migrate
您可以通过迁移到以前的迁移进行恢复。
例如使用下面的命令:
./manage.py migrate example_app one_left_to_the_last_migration
然后删除last_migration文件。
有一个很好的库可以使用它叫djagno-nomad,虽然没有直接关系到所问的问题,想分享这个,
场景:大多数情况下,当切换到项目时,我们觉得它应该恢复我们在当前分支上所做的更改,这正是这个库所做的,下面签出
https://pypi.org/project/django-nomad/
恢复迁移。
python manage.py migrate <APP_NAME> <MIGRATION_NUMBER_PREFIX>
MIGRATION_NUMBER_PREFIX是您要还原到的迁移的数字前缀,例如0001表示转到0001_initial.py迁移。然后您可以删除该迁移。
您可以使用0作为迁移号来恢复应用程序的所有迁移。
首先:找到你的应用程序之前的迁移,
Python manage.py showmigrations
eg:
bz
[X] 0001_initial
[ ] 0002_bazifff
如果您想要回滚0002_baziff迁移,
python manage.py migrate bz 0001_initial
如果要回滚0001_initial或all
python manage.py migrate bz zero
似乎只能回退0001
所有其他答案都非常适合回滚线性迁移。然而,当迁移是非线性的,即有多个叶节点,我们希望只回滚一条路径,那么我们可以这样做:
X
/ \
A B [A and B can represent any number of linear migrations.]
\ /
Y (merge migration)
如果我们需要回滚A,B和y,那么我们可以用其他答案状态的方式来做。 即python manage.py迁移应用X。
如果只需要取消回滚B和回滚Y,请执行以下步骤:
通过执行python manage.py迁移应用程序B(或A;这两个作品)。 暂时从项目位置移除迁移文件A和Y。 现在取消应用B,执行python manage.py迁移应用X。
将迁移文件A和Y带到原始位置。现在,如果您愿意,您可以安全地删除未应用的迁移B和Y。
要点是django只能回滚迁移,如果文件在位置中。如果您不想回滚一个迁移路径(例如这里的a),请在执行回滚时将其从项目位置中移除。
更多关于这个。https://stackoverflow.com/a/71231925/8663277