对我的Django应用程序模型进行了一些更改,并使用South在我的开发机器上迁移它们(迁移0004到0009)。但是当尝试在服务器上迁移这些更改时,我收到“GhostMigrations”错误。
没有太多好的内容可以解释ghost迁移是什么,或者如何调试它。 Google对此没有帮助,其他提及幽灵迁移的SO问题也没有涵盖这一点(最有用的问题here主要是关于工作流程)。 django-south IRC中有用的人对此进行了关于鬼迁移的说法:“这意味着南方的历史(数据库中的一个表)记录了它认为已经应用的两个迁移,但其迁移文件无法找到” 。我现在想弄清楚如何完成调试。
提前感谢您的帮助。
以下是错误:
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-south认为迁移0002和0003是“Ghosts”。它们都在迁移文件夹中,在迁移表中列为“已应用”,并且数据库似乎与迁移0003后的结束状态一致。
(可能的错误:迁移文件夹包含在git repo中;迁移0002创建了一个属性,然后0003重命名了它)
答案 0 :(得分:23)
不知何故,您的数据库记录了在迁移文件夹中找不到的迁移0002和0003。
文件系统中的迁移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+
。
您最了解当前数据库表应该匹配哪个迁移!
答案 1 :(得分:7)
它们被视为ghost迁移,因为数据库中的名称为:
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
添加到南数据库表中,然后更新这两行以便数字匹配您的文件名。
毋庸置疑,在此之前你应该备份所有内容。