Подтвердить что ты не робот

Что такое исключение Django South GhostMigrations и как его отлаживать?

Сделал некоторые изменения в моей модели приложений Django и использовал Юг, чтобы перенести их на мою машину разработки (миграции 0004 - 0009). Но когда вы пытаетесь перенести эти изменения на сервере, я получаю ошибку "GhostMigrations".

Не так много хорошего контента, объясняющего, что такое миграция призрака, или как отлаживать его. Google не был полезен в этом вопросе, а другие вопросы SO, в которых упоминаются миграции призраков, также не охватывают этот вопрос (наиболее полезный вопрос здесь в основном касался рабочего процесса). Полезные люди в IRC django-south имели это, чтобы сказать о миграции призраков: "это означает, что южная история (таблица в 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-south рассматривает миграции 0002 и 0003 как "Призраки". Оба они находятся в папке миграции, которые перечислены как "применены" в таблице переноса, и, как представляется, база данных согласуется с конечным состоянием после миграции 0003.

(возможные ошибки: папка миграции была включена в репозиторий git; миграция 0002 создала атрибут, а затем 0003 переименовала его)

4b9b3361

Ответ 1

Как-то, ваша база данных записала миграции 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+.

Вы бы лучше знали, какая миграция должна соответствовать текущей таблице БД!

Ответ 2

Они считаются миграциями призраков, потому что имена в базе данных:

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

Цифры являются частью имени файла и должны идеально соответствовать. Я не уверен, как вы достигли этого состояния, но если вы абсолютно уверены, что ваш DB соответствует тому, что находится в вашем файле 0004, вы можете добавить 0002_auto__chg_field_asset_username__chg_field_asset_title__chg_field_asset в южную таблицу DB, а затем обновить две строки, чтобы числа соответствовали вашим имена файлов.

Излишне говорить, что перед тем, как это сделать, вы должны поддержать все.