Jakie jest zalecane podejście do resetowania historii migracji za pomocą Django South?

153

Zebrałem sporo migracji przy użyciu South (0.7) i Django (1.1.2), które zaczynają zajmować sporo czasu w moich testach jednostkowych. Chciałbym zresetować linię bazową i rozpocząć nowy zestaw migracji. Przejrzałem dokumentację South , przeprowadziłem zwykłe wyszukiwanie w Google / Stackoverflow (np. „Django south (zresetuj LUB usuń LUB usuń) historię migracji”) i nie znalazłem nic oczywistego.

Jedno podejście, które rozważałem, obejmowałoby „rozpoczęcie od nowa” poprzez „usunięcie„ południa ”lub„ wyczyszczenie ”historii ręcznie (np. Wyczyszczenie tabeli db, usunięcie plików migracji z dyrektora migracji) i po prostu ponowne uruchomienie,

./manage.py schemamigration southtut --initial

Tak więc, jeśli ktoś zrobił to wcześniej i ma jakieś wskazówki / sugestie, byłby bardzo wdzięczny.

Glenn Snyder
źródło
czasami trzeba ręcznie dodać __init__.pydoappname/migrations
laike9m
2
Jak zresetować migracje w wersji 1.7 (z wbudowaną migracją)?
Timo
1
@Timo: docs.djangoproject.com/en/dev/topics/migrations/ ... może być podejściem. Możesz także po prostu usunąć migracje / katalogi i ponownie wydać, ./manage.py makemigrationsale jeśli nie zaczniesz od nowej
bazy danych,
Myślę, że squashmigrationsto właściwa odpowiedź
Julio Marins

Odpowiedzi:

121

EDYTUJ - umieszczam komentarz poniżej na górze tego, ponieważ ważne jest, aby go przeczytać przed> zaakceptowaną odpowiedzią, która następuje po @andybak

@Dominique: Twoja rada dotycząca manage.py reset south jest niebezpieczna i może zniszczyć bazę danych, jeśli w projekcie są używane aplikacje innych firm, jak wskazał @thnee poniżej. Ponieważ Twoja odpowiedź ma tak wiele pozytywnych głosów, bardzo bym wdzięczny, gdybyś mógł ją edytować i dodać przynajmniej ostrzeżenie o tym lub (nawet lepiej) zmienić to, aby odzwierciedlić podejście @hobs (co jest równie wygodne, ale nie wpływają na inne aplikacje) - dzięki! - chrisv Mar 26 '13 o 9:09

Zaakceptowana odpowiedź jest następująca:

Najpierw odpowiedź autora Południa :

O ile zadbasz o to, aby zrobić to na wszystkich wdrożeniach jednocześnie, nie powinno być z tym żadnego problemu. Osobiście zrobiłbym:

    rm -r appname/migrations/ 
    ./manage.py reset south 
    ./manage.py convert_to_south appname 

(Zauważ, że część „ reset south” czyści rekordy migracji dla WSZYSTKICH aplikacji, więc upewnij się, że uruchomiłeś pozostałe dwa wiersze dla wszystkich aplikacji lub usunąłeś je wybiórczo).

convert_to_southWezwanie na końcu tworzy nową migrację i fałszywy-Dotyczy to (ponieważ baza danych zawiera już odpowiednie tabele). Nie ma potrzeby usuwania wszystkich tabel aplikacji podczas procesu.

Oto, co robię na moim serwerze deweloperskim + produkcyjnym, kiedy muszę pozbyć się tych wszystkich niepotrzebnych migracji deweloperów:

  1. Upewnij się, że mamy ten sam schemat bazy danych po obu stronach
  2. usuń każdy folder migracji po obu stronach
  3. run ./manage.py resetuj południe (jak mówi post) po obu stronach = czyści stół południowy *
  4. uruchom ./manage.py convert_to_south po obu stronach (fałszywa migracja 0001)
  5. następnie mogę ponownie rozpocząć migrację i przekazać foldery migracji na moim serwerze

* z wyjątkiem sytuacji, gdy chcesz wyczyścić tylko jedną aplikację, jeśli tak, musisz edytować swoją tabelę south_history i usunąć tylko wpisy dotyczące Twojej aplikacji.

Dominique Guardiola
źródło
2
Tak dla porządku, odpowiedź autora z Południa była następująca: jeśli tylko zadbasz o to na wszystkich wdrożeniach jednocześnie, nie powinno być z tym żadnego problemu. Osobiście zrobiłbym: rm -r nazwa_aplikacji / migrations / ./manage.py reset południe ./manage.py convert_to_south nazwa aplikacji (Zauważ, że część „resetuj południe” czyści rekordy migracji dla WSZYSTKICH aplikacji, więc upewnij się, że albo uruchomiłeś pozostałe dwie linie dla wszystkich aplikacji lub usuń selektywnie).
Adriaan Tijsseling
2
Zauważ również, że jeśli upuścisz tabele, będziesz potrzebować manage.py schemamigration app name --initialzamiast convert_to_south.
Adriaan Tijsseling
7
Od wersji Django 1.5 polecenie zarządzania „reset” zostało usunięte. Zamiast tego będziesz chciał zrobić coś mniej więcej podobnego south.models.MigrationHistory.objects.all().delete().
Andrew B.
13
@Dominique: Twoja rada dotycząca manage.py reset southjest niebezpieczna i może zniszczyć bazę danych, jeśli w projekcie są używane aplikacje stron trzecich, jak wskazał @thnee poniżej. Ponieważ Twoja odpowiedź ma tak wiele pozytywnych głosów, bardzo bym wdzięczny, gdybyś mógł ją edytować i dodać przynajmniej ostrzeżenie o tym lub (nawet lepiej) zmienić to, aby odzwierciedlić podejście @hobs (co jest równie wygodne, ale nie wpływają na inne aplikacje) - dzięki!
chrisv
3
Dlaczego było to tak wysoko oceniane? Prawie NIGDY nie należy całkowicie usuwać tabeli south_migrationhistory. To całkowicie zepsułoby wszystkie zależne aplikacje z migracjami, których nie chcesz dotykać. Odpowiedź Hoba jest właściwa.
Cerin
188

Jeśli musisz wybiórczo (tylko dla jednej aplikacji) zresetować migracje, które trwają zbyt długo, to zadziałało.

rm <app-dir>/migrations/*
python manage.py schemamigration <app-name> --initial
python manage.py migrate <app-name> 0001 --fake  --delete-ghost-migrations

Nie zapomnij ręcznie przywrócić wszelkich zależności od innych aplikacji, dodając wiersze takie jak depends_on = (("<other_app_name>", "0001_initial"),("<yet_another_app_name>", "0001_initial"))do <app-dir>/migrations/0001_initial.pypliku, jako pierwszy atrybut w klasie migracji tuż poniżej class Migration(SchemaMigration):.

Możesz wtedy ./manage.py migrate <app-name> --fake --delete-ghost-migrationsw innych środowiskach, zgodnie z tą odpowiedzią SO . Oczywiście jeśli fałszywy Delete lub sfałszować migrate zeromusisz ręcznie usuwać lewej nad stołami db z migracją, takich jak ten .

Bardziej nuklearną opcją jest ./manage.py migrate --fake --delete-ghost-migrationsuruchomienie na żywo serwera wdrażania, po którym następuje [my] sqldump. Następnie potokuj zrzut do [my] sql w środowiskach, w których potrzebujesz zmigrowanej, w pełni zapełnionej bazy danych. Wiem, że południowe świętokradztwo, ale zadziałało dla mnie.

płyty
źródło
2
To, czego naprawdę chcę, to „weź models.py jako ewangelię i spraw, żebym był czysty od tego momentu”. Zachowuje w ten sposób możliwość skonfigurowania wdrożenia od podstaw lub pracy z istniejącym wdrożeniem.
Bryce
1
To właśnie to robi.
płyty kuchenne
2
@hobs Przez jakiś DependsOnUnknownMigrationczas udawałem nową początkową migrację. Dzięki Twojemu komentarzowi mogłem się domyślić, że powinienem zaktualizować depends_onoświadczenie wszędzie tam, gdzie odnosi się do tej aplikacji. To naprawdę najlepsza odpowiedź. Dzięki! :)
manu
55

Dzięki odpowiedziom Dominique Guardioli i płytom pomogło mi to rozwiązać trudny problem. Jednak jest kilka problemów z rozwiązaniem, oto moje podejście.

Stosując manage.py reset southto nie jest dobry pomysł , jeśli masz jakiekolwiek aplikacje firm trzecich , które wykorzystuje South, na przykład django-cms(w zasadzie wszystko wykorzystuje Południowa).

reset south usunie całą historię migracji dla wszystkich zainstalowanych aplikacji.

Teraz weź pod uwagę, że uaktualniasz do najnowszej wersji django-cms, będzie ona zawierała nowe migracje, takie jak 0009_do_something.py. Południe z pewnością będzie zdezorientowane, gdy spróbujesz przeprowadzić tę migrację bez 0001przechodzenia przez 0008historię migracji.

Znacznie lepiej / bezpieczniej jest selektywnie resetować tylko te aplikacje, które utrzymujesz .


Przede wszystkim upewnij się, że Twoje aplikacje nie mają desynchronizacji między migracjami na dysku a migracjami, które zostały wykonane w bazie danych. W przeciwnym razie wystąpi ból głowy.

1. Usuń historię migracji moich aplikacji

sql> delete from south_migrationhistory where app_name = 'my_app';

2. Usuń migracje moich aplikacji

$ rm -rf my_app/migrations/

3. Utwórz nowe początkowe migracje dla moich aplikacji

$ ./manage.py schemamigration --initial my_app

4. Fałszywe wykonanie początkowych migracji moich aplikacji

Spowoduje to wstawienie migracji do south_migrationhistorybez dotykania rzeczywistych tabel:

$ ./manage.py migrate --fake my_app

Krok 3 i 4 to właściwie tylko dłuższa odmiana manage.py convert_to_south my_app, ale wolę tę dodatkową kontrolę w tak delikatnej sytuacji, jak modyfikacja produkcyjnej bazy danych.

kolano
źródło
2
Zredagowałem moją odpowiedź, aby uwzględnić poprawki dla znalezionych problemów (po prostu zgadując na podstawie Twojej odpowiedzi) i przetestowałem ją w produkcyjnej bazie danych z milionami wierszy.
płyty kuchenne
2
To prawie to, co robimy. Jeśli korzystasz z opcji --delete-ghost-migrations w kroku 4, możesz pominąć krok 1.
tobych
Powinieneś jawnie określić nazwy aplikacji w, ./manage.py migrate --fakejeśli nie chcesz fałszywie migrować innych aplikacji, które mają oczekujące migracje.
wadim
2
@wadim Stąd krok 0: „upewnij się, że nie masz desynchronizacji między migracjami na dysku i migracjami, które zostały wykonane w bazie danych”.
thnee
@thnee Right. Prawdopodobnie warto wspomnieć, że odnosisz się do wszystkich zainstalowanych aplikacji w kroku 0. Czy znasz jednak łatwy sposób wykonania kroku 0?
wadim
7

Podobnie jak thnee (zobacz jej odpowiedź), używamy łagodniejszego podejścia do sugestii autora z Południa (Andrew Godwina) cytowanej w innym miejscu tutaj i oddzielamy to, co robimy z bazą kodu, od tego, co robimy z bazą danych podczas wdrażania ponieważ potrzebujemy powtarzalności wdrożeń:

Co robimy w kodzie:

# 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

Co robimy z bazą danych po wdrożeniu tego kodu

# Fake the migration history, wiping out the rest
$ ./manage.py migrate appname --fake --delete-ghost-migrations
tobych
źródło
Myślę, że zrobiłem to samo, ale ręcznie usunąłem wpisy bazy danych, zamiast używać --delete_ghoist-migrations. Twoja droga jest trochę przyjemniejsza.
wobbily_col,
1

Jeśli pracujesz tylko na maszynie deweloperskiej, napisałem polecenie zarządzania, które robi dokładnie to, co sugerował Dominique.

http://balzerg.blogspot.co.il/2012/09/django-app-reset-with-south.html

W przeciwieństwie do sugestii autora z południa, NIE SZKODZI to innych zainstalowanych aplikacji korzystających z południa.

idanzalz
źródło
A jeśli w przeciwieństwie do autora chcesz zachować istniejące migracje (tj. Chcesz zresetować aplikację, a także historię migracji, ale zachować aktualne migracje), możesz spróbować tego: goo.gl/0ZnWm
mgalgs
1

Następujące jest tylko wtedy, gdy chcesz zresetować wszystkie aplikacje. Przed przystąpieniem do tej pracy wykonaj kopię zapasową wszystkich baz danych. Zanotuj także swój depends_on w plikach początkowych, jeśli takie istnieją.

Raz:

(1) find . -type d -name migrations -exec git rm -rf '{}' \;
(2) find . -type d -name migrations -exec rm -rf '{}' \;
(3) ./manage.py schemamigration <APP_NAME> --initial
(4) [GIT COMMIT]

Przetestuj ładowanie projektu przed wypchnięciem. Następnie dla każdego komputera lokalnego / zdalnego zastosuj następujące czynności:

(5) [GIT PULL]
(6) ./manage.py reset south
(7) ./manage.py migrate --fake

Wykonaj wstępne (3) dla każdej aplikacji, którą chcesz ponownie zaangażować. Pamiętaj, że reset (6) usunie tylko historię migracji, dlatego nie jest szkodliwy dla bibliotek. Fałszywe migracje (7) spowodują przywrócenie historii migracji wszelkich zainstalowanych aplikacji innych firm.

yasc
źródło
0

usuń niezbędny plik z folderu aplikacji

ścieżka instancji

 cd /usr/local/lib/python2.7/dist-packages/wiki/south_migrations

wiki - to moja aplikacja

Andrei Eremchuk
źródło