2012-01-16 37 views
23

对我的Django应用程序模型做了一些更改,并使用South将它们迁移到我的开发计算机上(迁移0004至0009)。但是当试图在服务器上迁移这些更改时,出现“GhostMigrations”错误。什么是Django South GhostMigrations异常以及如何调试它?

解释什么是ghost迁移,或者如何调试,没有太多好的内容。谷歌对这一个没有帮助,而提到鬼迁移的其他SO问题也不包括这一点(最有帮助的问题here主要是关于工作流)。 django-south IRC中有帮助的人对此说过鬼迁移:“这意味着南的历史(db中的一个表)记录了它认为已经应用的两个迁移,但是其迁移文件找不到” 。我试图弄清楚现在如何完成调试。

在此先感谢您的帮助。

这里的错误:

Traceback (most recent call last): 
    File "manage.py", line 14, in <module> 
    execute_manager(settings) 
    File "/home/username/webapps/myproject/lib/python2.6/django/core/management/__init__.py", line 438, in execute_manager 
    utility.execute() 
    File "/home/username/webapps/myproject/lib/python2.6/django/core/management/__init__.py", line 379, in execute 
    self.fetch_command(subcommand).run_from_argv(self.argv) 
    File "/home/username/webapps/myproject/lib/python2.6/django/core/management/base.py", line 191, in run_from_argv 
    self.execute(*args, **options.__dict__) 
    File "/home/username/webapps/myproject/lib/python2.6/django/core/management/base.py", line 220, in execute 
    output = self.handle(*args, **options) 
    File "/home/username/lib/python2.6/South-0.7.3-py2.6.egg/south/management/commands/migrate.py", line 105, in handle 
    ignore_ghosts = ignore_ghosts, 
    File "/home/username/lib/python2.6/South-0.7.3-py2.6.egg/south/migration/__init__.py", line 171, in migrate_app 
    applied = check_migration_histories(applied, delete_ghosts, ignore_ghosts) 
    File "/home/username/lib/python2.6/South-0.7.3-py2.6.egg/south/migration/__init__.py", line 88, in check_migration_histories 
    raise exceptions.GhostMigrations(ghosts) 
south.exceptions.GhostMigrations: 

! These migrations are in the database but not on disk: 
    <bodyguard: 0002_auto__add_field_asset_is_reserved__add_field_asset_is_created__add_fie> 
    <bodyguard: 0003_auto__del_field_asset_is_reserved__add_field_asset_is_assigned> 
! I'm not trusting myself; either fix this yourself by fiddling 
! with the south_migrationhistory table, or pass --delete-ghost-migrations 
! to South to have it delete ALL of these records (this may not be good). 

我很惊讶地看到,南方抱怨迁移在0002和0003,因为我这些变化个月前提出。我今天早些时候所做的改变是改变0004至0009.

这里是我的模型:

class Asset(models.Model): 
    title = models.CharField(max_length=200, blank=True, null=True) 
    user = models.ForeignKey(User, blank=True, null=True) 
    is_assigned = models.NullBooleanField(blank=True, null=True) 
    is_created = models.NullBooleanField(blank=True, null=True) 
    is_active = models.NullBooleanField(blank=True, null=True) 
    activation_date = models.DateTimeField(default=datetime.datetime.now, blank=True, null=True) 

class AssetEdit(models.Model): 
    asset = models.ForeignKey(Asset, related_name="edits", blank=True, null=True) 
    update_date = models.DateTimeField(default=datetime.datetime.now, blank=True, null=True) 

这里是南迁移文件夹的内容:

0001_initial.py 
0001_initial.pyc 
0002_auto__chg_field_asset_username__chg_field_asset_title__chg_field_asset.py 
0002_auto__chg_field_asset_username__chg_field_asset_title__chg_field_asset.pyc 
0003_auto__add_field_asset_is_reserved__add_field_asset_is_created__add_fie.py 
0003_auto__add_field_asset_is_reserved__add_field_asset_is_created__add_fie.pyc 
0004_auto__del_field_asset_is_reserved__add_field_asset_is_assigned.py 
0004_auto__del_field_asset_is_reserved__add_field_asset_is_assigned.pyc 
0005_auto__add_assetedit.py 
0005_auto__add_assetedit.pyc 
0006_auto__del_field_assetedit_user__add_field_assetedit_asset.py 
0006_auto__del_field_assetedit_user__add_field_assetedit_asset.pyc 
0007_auto__chg_field_assetedit_update_date.py 
0007_auto__chg_field_assetedit_update_date.pyc 
0008_auto__add_field_asset_activated_date.py 
0008_auto__add_field_asset_activated_date.pyc 
0009_auto__del_field_asset_activated_date__add_field_asset_activation_date.py 
0009_auto__del_field_asset_activated_date__add_field_asset_activation_date.pyc 
__init__.py 
__init__.pyc 

这是south_migrationtable:

id | app_name |         migration         |   applied    
----+-----------+-----------------------------------------------------------------------------+------------------------------- 
    1 | myapp  | 0001_initial                | 2011-10-14 22:07:11.467184-05 
    2 | myapp  | 0002_auto__add_field_asset_is_reserved__add_field_asset_is_created__add_fie | 2011-10-14 22:07:11.469822-05 
    3 | myapp  | 0003_auto__del_field_asset_is_reserved__add_field_asset_is_assigned   | 2011-10-14 22:07:11.471799-05 
(3 rows) 

这是myapp_asset表,因为它目前为:

        Table "public.myapp_asset" 
    Column |   Type   |       Modifiers       
-------------+------------------------+-------------------------------------------------------------- 
id   | integer    | not null default nextval('myapp_asset_id_seq'::regclass) 
title  | character varying(200) | 
user_id  | integer    | 
is_assigned | boolean    | 
is_created | boolean    | 
is_active | boolean    | 
Indexes: 
    "myapp_asset_pkey" PRIMARY KEY, btree (id) 
    "myapp_asset_user_id" btree (user_id) 
Foreign-key constraints: 
    "myapp_asset_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED 

我想不通为什么 Django的南认为迁移在0002和0003是“鬼”。它们都位于迁移文件夹中,在迁移表中列为“已应用”,并且数据库似乎与迁移后的最终状态0003一致。

(可能的错误:迁移文件夹包含在git repo;迁移0002创建了一个属性,然后0003重命名了它)

回答

23

不知何故,您的数据库已记录migrations 0002和0003,它无法在您的migrations文件夹中找到。

迁移0002在你的文件系统是0002_auto__chg_field_asset_username__chg_field_asset_title__chg_field_asset.py,而在历史记录表中,在它的0002_auto__add_field_asset_is_reserved__add_field_asset_is_created__add_fie.py

南必须在迁移过程的文件夹有不同的内容已被迁移(可能发展?)。

基于你在说什么,它看起来对我来说,你的数据库反映迁移0004的状态,所以我会运行一个python manage.py migrate myapp 0004 --fake --delete-ghost-migrations将设置迁移表在您添加的is_assigned场点,和你可以愉快地申请迁移0005+

你最好知道哪个迁移当前DB表应该匹配!

+0

谢谢Yuji。快速提问:在--delete-ghost-migrations中究竟发生了什么? South是否只从south_migrationtable中移除这些行并将其替换为正确的行?我问,因为迁移0002和0003中创建的字段已经填充。 South不会放弃这些数据并重新创建它,是吗? – jchung 2012-01-16 04:56:50

+1

@Jared,不,它只会修改'south_migrationhistory'表。尽管如此,你仍然需要指定'--fake',因为你的db已经反映了这些变化(或者甚至更多 - 但是我无法从你的信息中得知),因为南方在应用“真正”迁移2,3和4时会失败代码示例) – 2012-01-16 05:02:35

+0

更新:问题解决了! Thx – jchung 2012-01-16 21:03:48

7

它们被认为是鬼迁移,因为在数据库中的名称:

0002_auto__add_field_asset_is_reserved__add_field_asset_is_created__add_fie 
0003_auto__del_field_asset_is_reserved__add_field_asset_is_assigned 

不匹配你列出的文件名:

0003_auto__add_field_asset_is_reserved__add_field_asset_is_created__add_fie.py 
0004_auto__del_field_asset_is_reserved__add_field_asset_is_assigned.py 

的数字是文件名的一部分,必须完全匹配。我不确定你是如何到达这个状态的,但是如果你确定你的数据库与你的0004文件中的内容相匹配,你可以在南数据库表中添加0002_auto__chg_field_asset_username__chg_field_asset_title__chg_field_asset,然后更新这两行,使得这些数字与你的文件名匹配。

不用说,在做这件事之前你应该支持所有事情。

+0

看起来像迁移文件夹中所述,第一次迁移(0001initial)包括迁移0001和0002。这将解释为什么迁移数字不同步。很明显,在我的工作流程中出现错误因此,如果我只修复数据库中的行,这将使南方恢复同步,对吧?然后,在做出修复之后,我会再次运行“迁移”以让南迁移至迁移0009(这正是我试图获得的目标)吗? – jchung 2012-01-16 04:41:32

+0

是,或者“迁移myapp --fake”,迁移到您知道您的数据库当前使用'--delete-ghost-migrations'参数表示并删除ghost迁移的点。 – 2012-01-16 04:48:40

+0

更新:问题解决了!谢谢 – jchung 2012-01-16 21:04:11

相关问题