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

Gle*_*der 154 django django-south

我使用South(0.7)和Django(1.1.2)积累了大量的迁移,这些迁移在我的单元测试中开始消耗相当多的时间.我想重置基线并开始一系列新的迁移.我查看了南方文档,完成了通常的Google/Stackoverflow搜索(例如"django south(重置或删除或删除)迁移历史记录")并且没有找到任何明显的内容.

我已经考虑过的一种方法是通过"删除"南方或"清除"历史记录(例如清除数据库表,从迁移控制器中删除迁移文件)来"重新开始",然后重新运行,

./manage.py schemamigration southtut --initial

所以,如果有人之前已经这样做并有一些提示/建议,他们将不胜感激.

hob*_*obs 188

如果您需要有选择地(仅针对一个应用程序)重置花费太长时间的迁移,对我有用.

rm <app-dir>/migrations/*
python manage.py schemamigration <app-name> --initial
python manage.py migrate <app-name> 0001 --fake  --delete-ghost-migrations
Run Code Online (Sandbox Code Playgroud)

不要忘记手动还原任何依赖加入般的线条上的其他应用程序depends_on = (("<other_app_name>", "0001_initial"),("<yet_another_app_name>", "0001_initial"))到您的<app-dir>/migrations/0001_initial.py文件,如略低于迁移类的第一个属性class 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中.南亵渎,我知道,但为我工作.

  • 这是最好的答案,我希望它能得到更多的回报. (12认同)
  • 我真正想要的是"把models.py作为福音,从那时起让我干净利落".因此,保留了从头开始设置部署或从现有部署开始工作的能力. (2认同)
  • @hobs在伪造新的初始迁移时,我得到了一个`DependsOnUnknownMigration`.感谢您的评论,我可以理解我应该更新`depends_on`语句,只要它引用此应用程序.这真的是最好的答案.谢谢!:) (2认同)

Dom*_*ola 122

编辑 - 我在下面添加评论,因为在@andybak之后接受的答案之前阅读它是很重要的

@Dominique:关于manage.py reset south的建议是危险的,如果在项目中有任何使用south的第三方应用程序,可能会破坏数据库,如下面@thnee所指出的那样.既然你的答案有这么多的赞成,我真的很感激你,如果你可以编辑它并至少添加一个警告,或者(甚至更好)改变它以反映@hobs方法(这同样方便,但不是影响其他应用程序) - 谢谢! - chrisv 2013年3月26日9:09

接受的答案如下:

首先,南方作者的回答:

只要您在所有部署中同时注意这一点,就不应该有任何问题.就个人而言,我会这样做:

    rm -r appname/migrations/ 
    ./manage.py reset south 
    ./manage.py convert_to_south appname 
Run Code Online (Sandbox Code Playgroud)

(请注意," reset south"部分会清除所有应用的迁移记录,因此请确保为所有应用运行其他两行或选择性删除).

最后的convert_to_south调用会进行新的迁移并伪造它(因为您的数据库已经有相应的表).在此过程中无需删除所有应用程序表.

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

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

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

  • @Dominique:关于`manage.py reset south`的建议是**危险****如果在项目中有任何使用south的第三方应用程序,**可能会破坏数据库**,如下面@thnee所指出的.既然你的答案有这么多的赞成,我真的很感激你,如果你可以编辑它并至少添加一个警告,或者(甚至更好)改变它以反映@hobs方法(这同样方便,但不是影响其他应用程序) - 谢谢! (13认同)
  • 从Django 1.5开始,"重置"管理命令消失了.相反,你会想要做一些像`south.models.MigrationHistory.objects.all().delete()`这样的事情. (7认同)
  • 为什么这么高度投票?您几乎不应该完全删除您的south_migrationhistory表.这将完全搞砸任何您不想触及的迁移的相关应用程序.滚刀的答案是正确的. (3认同)
  • 仅作为记录,南方作者的回答如下:只要您在所有部署中同时注意这一点,就不应该有任何问题.就个人而言,我会这样做:rm -r appname/migrations/./manage.py重置南./manage.py convert_to_south appname(请注意,"reset south"部分会清除所有应用的迁移记录,因此请确保您运行所有应用程序的其他两行或删除选择性). (2认同)
  • 另请注意,如果删除表,则需要`manage.py schemamigration app name --initial`而不是convert_to_south. (2认同)

thn*_*nee 55

感谢Dominique Guardiola和滚刀的回答,它帮助我解决了一个难题.但是解决方案存在一些问题,这是我的看法.

使用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';
Run Code Online (Sandbox Code Playgroud)

2.删除我的应用的迁移

$ rm -rf my_app/migrations/
Run Code Online (Sandbox Code Playgroud)

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

$ ./manage.py schemamigration --initial my_app
Run Code Online (Sandbox Code Playgroud)

4.假执行我的应用程序的初始迁移

这会将迁移插入到south_migrationhistory不触及实际表的情况中:

$ ./manage.py migrate --fake my_app
Run Code Online (Sandbox Code Playgroud)

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

  • 我编辑了我的答案,为你发现的问题加入了修复程序(根据你的答案猜测它们),并在具有数百万行的生产数据库上测试它. (2认同)
  • 这几乎就是我们正在做的事情.如果在步骤4中使用--delete-ghost-migrations选项,则可以省略步骤1. (2认同)
  • @wadim因此,步骤0:"确保磁盘上的迁移与已在数据库上执行的迁移之间没有异步". (2认同)

tob*_*ych 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
Run Code Online (Sandbox Code Playgroud)

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

# Fake the migration history, wiping out the rest
$ ./manage.py migrate appname --fake --delete-ghost-migrations
Run Code Online (Sandbox Code Playgroud)