2012-01-16 11 views
23

Wprowadziłem kilka zmian w moim modelu aplikacji Django i wykorzystałem South do migracji na moim komputerze programistycznym (migracje od 0004 do 0009). Ale podczas próby migracji tych zmian na serwerze pojawia się błąd "GhostMigrations".Co to jest wyjątek Django South GhostMigrations i jak go debugować?

Nie ma zbyt wielu dobrych treści wyjaśniających, czym jest migracja ducha lub jak ją usunąć. Google nie był pomocny w tej sprawie, a pozostałe pytania dotyczące SO, które wspominają o migracji ducha, również tego nie uwzględniają (najbardziej pomocne pytanie dotyczyło głównie przepływu pracy). Pomocni ludzie w IRC django-south mieli to do powiedzenia na temat migracji ducha: "to oznacza historię Południa (tabela w bazie danych) rejestruje dwie migracje, które według niej zostały zastosowane, ale których plików migracji nie może znaleźć" . Próbuję teraz dowiedzieć się, jak zakończyć debugowanie.

Z góry dziękujemy za pomoc.

Oto błąd:

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). 

Byłem zaskoczony, aby zobaczyć, że South narzekali migracje 0002 i 0003, ponieważ zrobiłem te zmiany miesięcy temu. Zmiany zrobiłem wcześniej już były zmiany w 0004 przez 0009.

Oto mój model:

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) 

Oto zawartość folderu migracje południe:

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 

To jest 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) 

To myapp_asset tabeli w obecnym brzmieniu:

        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 

Nie mogę zrozumieć, dlaczego django-południe uważa migracje 0002 i 0003 za "duchy". Oba znajdują się w folderze migracji, są wymienione jako "zastosowane" w tabeli migracji, a baza danych wydaje się być zgodna ze stanem końcowym po migracji 0003.

(Możliwe błędy: folder migracji został uwzględniony w git repo; migracja 0002 utworzyła atrybut, a następnie 0003 zmieniła jego nazwę)

Odpowiedz

23

W pewien sposób Twoja baza danych zarejestrowała migrację 0002 i 0003, której nie może znaleźć w folderze migracji.

Migracja 0002 w systemie plików jest 0002_auto__chg_field_asset_username__chg_field_asset_title__chg_field_asset.py natomiast w tabeli w historii to 0002_auto__add_field_asset_is_reserved__add_field_asset_is_created__add_fie.py

Południowa musiały zostać przeniesione gdy folder migracje miały różne treści (być może w rozwoju?).

Na podstawie tego, co mówisz, to mi wygląda baza danych odzwierciedla stan na migrację 0004, tak bym uruchomić python manage.py migrate myapp 0004 --fake --delete-ghost-migrations który będzie ustawić tabeli migracji w punkcie dodanego pola is_assigned, a ty mogą z powodzeniem stosować migracje 0005+.

Najlepiej byłoby wiedzieć, która migracja bieżącego stołu DB powinna być zgodna z!

+0

Dzięki Yuji. Szybkie pytanie: co dokładnie dzieje się w migracji - dset-duch? Czy South usuwa te wiersze z south_migrationtable i zastępuje je odpowiednimi wierszami? Pytam, ponieważ pola utworzone w migracji 0002 i 0003 zostały już wypełnione. Południe nie upuści tych danych i nie stworzy ich ponownie, prawda? – jchung

+1

@Jared, nie zmieni to tylko tabeli 'south_migrationhistory'. Nadal będziesz musiał podać '--fake', ponieważ na południu nie uda się zastosować" prawdziwej "migracji 2, 3 i 4, ponieważ twój db już odzwierciedla te zmiany (lub może nawet więcej - ale nie mogę powiedzieć od ciebie sam przykład kodu) –

+0

Aktualizacja: problem rozwiązany! Thx – jchung

7

Są one uważane migracje duchach, ponieważ nazwy w bazie danych:

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 

nie pasuje do nazwy plików masz listę:

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 

Liczby są częścią nazwy pliku i musi pasować idealnie . Nie jestem pewien, w jaki sposób osiągnąłeś ten stan, ale jeśli jesteś absolutnie pewien, że twój DB pasuje do tego, co jest w twoim pliku 0004, możesz dodać 0002_auto__chg_field_asset_username__chg_field_asset_title__chg_field_asset do tabeli South DB, a następnie zaktualizować dwa wiersze, aby numery pasowały do ​​twoich nazw plików.

Nie trzeba dodawać, że należy wszystko z powrotem zrobić, zanim to zrobimy.

+0

Wygląda na to, że pierwszy przebieg migracji (0001initial) obejmuje obie migracje 0001 i 0002 zgodnie z opisem w folderze migracji. To wyjaśniałoby, dlaczego numery migracji nie były zsynchronizowane. Najwyraźniej błąd w moim przepływie pracy. Więc jeśli po prostu naprawię wiersze w bazie danych, spowoduje to zsynchronizowanie South, prawda? Następnie, po wprowadzeniu tej poprawki, uruchomiłbym "migrowanie" ponownie, aby przesunąć Południe do migracji 0009 (gdzie próbuję uzyskać)? – jchung

+0

Tak, lub 'migrate myapp --fake' migracja do punktu, o którym wiesz, że twoja baza danych aktualnie reprezentuje i usuwa migracje ducha za pomocą argumentu' --delete-ghost-migrations'. –

+0

Aktualizacja: problem rozwiązany! Dzięki – jchung

Powiązane problemy