建议使用Django South重置迁移历史记录的方法是什么?


153

我已经使用South(0.7)和Django(1.1.2)积累了很多迁移,这些迁移在我的单元测试中开始占用大量时间。我想重置基准并开始新的迁移。我已经阅读了South文档,进行了常规的Google / Stackoverflow搜索(例如“ django south(重置或删除或删除)迁移历史记录”),但没有发现任何明显的内容。

我考虑过的一种方法是通过“删除” South或手动“清除”历史记录来“重新开始”(例如清除db表,从Migrations Director中删除迁移文件),然后重新运行,

./manage.py schemamigration southtut --initial

因此,如果有人以前这样做过,并且有一些提示/建议,将不胜感激。


有时您需要手动添加__init__.pyappname/migrations
laike9m 2014年

2
如何在1.7中重置迁移(使用内置迁移)?
2014年

1
@Timo:docs.djangoproject.com/en/dev/topics/migrations/…可能是一种方法。您也可以只删除您的迁移/目录并重新发布,./manage.py makemigrations但是如果您不从新的数据库开始,则会发生坏事...
Jocelyn delalande 2014年

我认为这squashmigrations是正确的答案
Julio Marins

Answers:


121

编辑-我在此顶部上方添加评论,因为在@andybak后面的>接受答案之前阅读它很重要

@Dominique:有关@ manage.py的建议很危险,并且如果项目中有任何第三方应用程序在使用South,则可能会破坏数据库。由于您的答案有很多反对意见,如果您可以对其进行编辑并至少添加一条警告,或者(甚至更好)将其更改为反映@hobs方法(这很方便,但是没有这样做),我将不胜感激。影响其他应用程序)-谢谢!–克里斯夫13年3月26日9:09

接受的答案如下:

首先,南方作家的回答

只要您注意同时在所有部署上执行此操作,就不会有任何问题。就个人而言,我会:

    rm -r appname/migrations/ 
    ./manage.py reset south 
    ./manage.py convert_to_south appname 

(请注意,“ reset south”部分会清除所有应用程序的迁移记录,因此请确保您为所有应用程序运行另外两行或有选择地删除)。

最后的convert_to_south调用进行了新的迁移并对其进行了虚假应用(因为您的数据库已经具有相应的表)。在此过程中,无需删除所有应用程序表。

当我需要摆脱所有这些不需要的开发迁移时,这就是我在开发+生产服务器上正在做的事情:

  1. 确保双方都有相同的数据库架构
  2. 删除两侧的每个迁移文件夹
  3. 运行./manage.py在两侧重置南(如帖子所述)=清除南表*
  4. 在两侧运行./manage.py convert_to_south(伪造0001迁移)
  5. 然后我可以重新开始进行迁移并在服务器上推送迁移文件夹

*除非您只想清理一个应用程序,否则,您将需要编辑south_history表并仅删除有关您应用程序的条目。


2
仅作记录,South作者的回答如下:只要您注意在所有部署上同时进行,就不会有任何问题。就个人而言,我会这样做:rm -r appname / migrations / ./manage.py reset south ./manage.py convert_to_south应用名(注意,“向南复位”部分会清除所有应用的迁移记录,因此请确保您都可以运行所有应用的其他两行或有选择地删除)。
Adriaan Tijsseling

2
还要注意,如果删除表,则需要manage.py schemamigration app name --initial而不是convert_to_south。
Adriaan Tijsseling 2011年

7
从Django 1.5开始,“重置”管理命令消失了。相反,您需要做类似的事情south.models.MigrationHistory.objects.all().delete()
安德鲁B.

13
@Dominique:您的建议manage.py reset south危险,并且如果项目中有任何第三方应用程序使用South,则可能会破坏数据库,如下面的@thnee所指出的。由于您的答案有很多反对意见,如果您可以对其进行编辑并至少添加一条警告,或者(甚至更好)将其更改为反映@hobs方法(我很方便,但没有这样做),我将不胜感激。影响其他应用程序)-谢谢!
克里斯夫

3
为什么如此强烈反对?您几乎永远不要完全删除您的south_migrationhistory表。这将使您不想接触的迁移彻底破坏所有依赖的应用程序。霍布的答案是正确的。
塞林

188

如果您需要选择性地(仅针对一个应用)重置重置时间太长的迁移,对我来说很有效。

rm <app-dir>/migrations/*
python manage.py schemamigration <app-name> --initial
python manage.py migrate <app-name> 0001 --fake  --delete-ghost-migrations

别忘了通过在文件中添加像这样的行作为迁移类中的第一个属性,来手动恢复对其他应用程序的任何依赖关系depends_on = (("<other_app_name>", "0001_initial"),("<yet_another_app_name>", "0001_initial"))<app-dir>/migrations/0001_initial.pyclass Migration(SchemaMigration):

然后./manage.py migrate <app-name> --fake --delete-ghost-migrations,您可以根据此SO答案在其他环境中。当然,如果你假的删除或假的migrate zero,你需要手动删除任何遗留的数据库表中包含迁移这样

另一个核心选​​择是./manage.py migrate --fake --delete-ghost-migrations在实时部署服务器上,然后是[my] sqldump。然后,在需要迁移的,完全填充的数据库的环境中,将转储通过管道传输到[my] sql。我知道南祭祀,但为我工作。


2
我真正想要的是“把models.py当作福音,从那时起让我变得干净”。因此,保留了从头开始设置部署或从现有部署进行工作的能力。
布莱斯2014年

1
这就是这样做的。
滚刀2014年

2
@hobs我正在DependsOnUnknownMigration假一会儿新的初始迁移。感谢您的评论,我想出了depends_on无论该引用该应用程序在哪里,我都应该更新该语句。这确实是最好的答案。谢谢!:)
manu 2014年

55

感谢多米尼克·瓜迪奥拉(Dominique Guardiola)和滚刀的回答,它帮助我解决了一个难题。但是,该解决方案有两个问题,这是我的看法。

例如,如果您有任何使用South的第三方应用程序(基本上所有东西都使用South),则使用该manage.py reset south方法不是一个好主意django-cms

reset south 将删除您已安装的所有应用程序的所有迁移历史记录。

现在考虑您升级到的最新版本django-cms,它将包含的新迁移0009_do_something.py。当您尝试运行迁移而无需南一定会混淆0001通过0008在迁移的历史。

选择性地仅重置您要维护的应用程序会更好/更安全。


首先,请确保您的应用程序在磁盘上的迁移与已在数据库上执行的迁移之间没有任何不同步。否则会头疼。

1.删​​除我的应用程序的迁移历史记录

sql> delete from south_migrationhistory where app_name = 'my_app';

2.删除我的应用程序的迁移

$ rm -rf my_app/migrations/

3.为我的应用程序创建新的初始迁移

$ ./manage.py schemamigration --initial my_app

4.伪造我的应用程序的初始迁移

这将在south_migrationhistory不涉及实际表的情况下插入迁移:

$ ./manage.py migrate --fake my_app

第3步和第4步实际上只是的一个较长的变体manage.py convert_to_south my_app,但是在修改生产数据库这样微妙的情况下,我更喜欢额外的控制。


2
我编辑了答案,以包含针对您发现的问题的修复程序(仅根据您的答案猜测它们),并在具有数百万行的生产数据库中对其进行了测试。
滚刀

2
这几乎就是我们正在做的。如果您使用--delete幻像迁移选项在步骤4,你可以离开了第1步
tobych

./manage.py migrate --fake如果您不想伪造迁移其他有待迁移的应用程序,则应在其中明确指定应用程序名称。
wadim 2013年

2
@wadim因此,第0步:“确保磁盘上的迁移与数据库上已执行的迁移之间没有同步”。
thnee

@thnee对。可能值得一提的是,您在步骤0中引用了所有已安装的应用程序。您知道执行步骤0的简便方法吗?
wadim

7

像thnee(请参阅她的回答)一样,我们对南方作者(Andrew Godwin)在这里其他地方引用的建议也采用了较为温和的方法,并且在部署过程中,我们将对代码库的处理与对数据库的处理分开,因为我们需要可重复的部署:

我们在代码中做什么:

# Remove all the migrations from the app
$ rm -fR appname/migrations
# Make the first migration (don't touch the database)
$ ./manage.py schemamigration appname --initial

部署代码后,我们对数据库执行的操作

# Fake the migration history, wiping out the rest
$ ./manage.py migrate appname --fake --delete-ghost-migrations

我想我只是做了同样的事情,只是手动删除数据库条目,而不是使用--delete_ghoist-migrations。您的方法更好一些。
wobbily_col 2014年

1

如果您只是在开发机器上工作,我编写了一个管理命令,该命令几乎可以完成Dominique的建议。

http://balzerg.blogspot.co.il/2012/09/django-app-reset-with-south.html

与south的作者建议相反,这不会危害使用south的其他已安装应用程序。


并且,如果与作者不同,如果您希望保留现有的迁移(即,您想重置应用程序和迁移历史记录,但保留实际的迁移),那么您可以尝试以下操作:goo.gl/0ZnWm
mgalgs

1

仅当您想重置所有应用程序时,才进行以下操作。在进行此工作之前,请备份所有数据库。还要记下初始文件中的depends_on(如果有)。

一次:

(1) find . -type d -name migrations -exec git rm -rf '{}' \;
(2) find . -type d -name migrations -exec rm -rf '{}' \;
(3) ./manage.py schemamigration <APP_NAME> --initial
(4) [GIT COMMIT]

在推送之前测试引导您的项目。然后,对于每台本地/远程计算机,请执行以下操作:

(5) [GIT PULL]
(6) ./manage.py reset south
(7) ./manage.py migrate --fake

对要重新参与的每个应用进行初始(3)。请注意,reset(6)将仅删除迁移历史记录,因此对库无害。假迁移(7)将返回已安装的任何第三方应用程序的迁移历史记录。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.