Was ist der empfohlene Ansatz zum Zurücksetzen des Migrationsverlaufs mit Django South?

153

Ich habe einige Migrationen mit South (0.7) und Django (1.1.2) gesammelt, die in meinen Unit-Tests ziemlich viel Zeit in Anspruch nehmen. Ich möchte die Basislinie zurücksetzen und eine neue Reihe von Migrationen starten. Ich habe die South-Dokumentation überprüft , die übliche Google / Stackoverflow-Suche durchgeführt (z. B. "Migrationsverlauf für Django South (Zurücksetzen ODER Löschen ODER Entfernen)") und nichts Offensichtliches gefunden.

Ein Ansatz, den ich in Betracht gezogen habe, besteht darin, "von vorne zu beginnen", indem "South" entfernt oder der Verlauf manuell "gelöscht" wird (z. B. die DB-Tabelle löschen, Migrationsdateien aus dem Migrationsdirektor entfernen) und einfach erneut ausgeführt werden.

./manage.py Schema Migration Southtut --initial

Wenn jemand dies schon einmal getan hat und einige Tipps / Vorschläge hat, wäre er sehr dankbar.

Glenn Snyder
quelle
manchmal müssen Sie manuell __init__.pyzuappname/migrations
laike9m
2
Wie setzen Sie die Migrationen in 1.7 zurück (mit der integrierten Migration)?
Timo
1
@ Timo: docs.djangoproject.com/de/dev/topics/migrations/… könnte ein Ansatz sein. Sie können auch einfach Ihre Migrationen / Verzeichnisse entfernen und erneut ausgeben, ./manage.py makemigrationsaber schlimme Dinge werden passieren, wenn Sie nicht von einer neuen
Datenbank ausgehen
Ich denke, squashmigrationsist die richtige Antwort
Julio Marins

Antworten:

121

BEARBEITEN - Ich setze oben einen Kommentar ein, da es wichtig ist, ihn vor der> akzeptierten Antwort zu lesen, die auf @andybak folgt

@Dominique: Ihr Rat bezüglich des Zurücksetzens von manage.py nach Süden ist gefährlich und kann die Datenbank zerstören, wenn im Projekt Apps von Drittanbietern verwendet werden, die South verwenden, wie von @thnee unten ausgeführt. Da Ihre Antwort so viele positive Stimmen hat, würde ich es wirklich begrüßen, wenn Sie sie bearbeiten und zumindest eine Warnung dazu hinzufügen oder (noch besser) ändern könnten, um den @ hobs-Ansatz widerzuspiegeln (was genauso praktisch ist, aber nicht andere Apps beeinflussen) - danke! - Chrisv 26. März 13 um 9:09 Uhr

Die akzeptierte Antwort folgt unten:

Zunächst eine Antwort des Südautors :

Solange Sie darauf achten, dass dies bei allen Bereitstellungen gleichzeitig durchgeführt wird, sollte dies kein Problem darstellen. Persönlich würde ich tun:

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

(Beachten Sie, dass der reset southTeil " " Migrationsdatensätze für ALLE Apps löscht. Stellen Sie daher sicher, dass Sie entweder die beiden anderen Zeilen für alle Apps ausführen oder selektiv löschen.)

Der convert_to_southAufruf am Ende führt eine neue Migration durch und wendet sie fälschlicherweise an (da Ihre Datenbank bereits die entsprechenden Tabellen enthält). Es ist nicht erforderlich, alle App-Tabellen während des Vorgangs zu löschen.

Folgendes mache ich auf meinem dev + -Produktionsserver, wenn ich all diese nicht benötigten dev-Migrationen entfernen muss:

  1. Stellen Sie sicher, dass auf beiden Seiten dasselbe DB-Schema vorhanden ist
  2. Löschen Sie jeden Migrationsordner auf beiden Seiten
  3. run ./manage.py auf beiden Seiten nach Süden zurücksetzen (wie im Beitrag angegeben) = löscht die Südtabelle *
  4. Führen Sie auf beiden Seiten ./manage.py convert_to_south aus (Fälschung der 0001-Migration).
  5. Dann kann ich neu starten, um Migrationen durchzuführen und die Migrationsordner auf meinem Server zu verschieben

* außer wenn Sie unter anderem nur eine App bereinigen möchten, müssen Sie in diesem Fall Ihre south_history-Tabelle bearbeiten und nur die Einträge zu Ihrer App löschen.

Dominique Guardiola
quelle
2
Nur zur Veranschaulichung, die Antwort des Südautors lautete wie folgt: Solange Sie darauf achten, dies bei allen Bereitstellungen gleichzeitig zu tun, sollte dies kein Problem darstellen. Persönlich würde ich Folgendes tun: rm -r appname / migrations / ./manage.py reset south ./manage.py convert_to_south appname (Beachten Sie, dass der Teil "reset south" Migrationsdatensätze für ALLE Apps löscht, stellen Sie also sicher, dass Sie beide ausführen die anderen beiden Zeilen für alle Apps oder selektiv löschen).
Adriaan Tijsseling
2
Beachten Sie auch, dass Sie, wenn Sie die Tabellen manage.py schemamigration app name --initiallöschen, anstelle von convert_to_south benötigen .
Adriaan Tijsseling
7
Ab Django 1.5 ist der Verwaltungsbefehl "Zurücksetzen" weg. Stattdessen möchten Sie etwas in etwa tun south.models.MigrationHistory.objects.all().delete().
Andrew B.
13
@Dominique: Ihre diesbezüglichen Ratschläge manage.py reset southsind gefährlich und können die Datenbank zerstören, wenn im Projekt Apps von Drittanbietern verwendet werden, die South verwenden, wie von @thnee unten ausgeführt. Da Ihre Antwort so viele positive Stimmen hat, würde ich es sehr begrüßen, wenn Sie sie bearbeiten und zumindest eine Warnung dazu hinzufügen oder (noch besser) ändern könnten, um den @ hobs-Ansatz widerzuspiegeln (was genauso praktisch ist, aber nicht andere Apps beeinflussen) - danke!
Chrisv
3
Warum wurde das so hoch bewertet? Sie sollten Ihre Tabelle south_migrationhistory fast NIE vollständig löschen. Das würde alle abhängigen Apps mit Migrationen, die Sie nicht berühren möchten, völlig durcheinander bringen. Hob's Antwort ist die richtige.
Cerin
188

Wenn Sie Migrationen, die zu lange dauern, selektiv (nur für eine App) zurücksetzen müssen, hat dies bei mir funktioniert.

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

Vergessen Sie nicht, Abhängigkeiten von anderen Apps manuell wiederherzustellen, indem Sie Zeilen wie depends_on = (("<other_app_name>", "0001_initial"),("<yet_another_app_name>", "0001_initial"))Ihre <app-dir>/migrations/0001_initial.pyDatei als erstes Attribut in Ihrer Migrationsklasse hinzufügen class Migration(SchemaMigration):.

Sie können dann ./manage.py migrate <app-name> --fake --delete-ghost-migrationsin anderen Umgebungen gemäß dieser SO-Antwort . Natürlich , wenn Sie fälschen die Lösch- oder fälschen die migrate zeroSie manuell benötigen, um wie alle übrig gebliebenen db Tabellen mit Migrations löschen diese .

Eine nuklearere Option ist die Verwendung ./manage.py migrate --fake --delete-ghost-migrationsauf dem Live-Bereitstellungsserver, gefolgt von einem [my] sqldump. Leiten Sie dann diesen Speicherauszug in [my] sql in den Umgebungen weiter, in denen Sie die migrierte, vollständig ausgefüllte Datenbank benötigen. Südsakrileg, ich weiß, aber für mich gearbeitet.

Kochfelder
quelle
2
Was ich wirklich will, ist "nimm models.py als Evangelium und mache mich von diesem Punkt an sauber". So bleibt die Möglichkeit erhalten, eine Bereitstellung von Grund auf neu einzurichten oder von einer vorhandenen Bereitstellung aus zu arbeiten.
Bryce
1
Das macht das.
Kochfelder
2
@hobs Ich habe eine DependsOnUnknownMigrationWeile die neue anfängliche Migration vorgetäuscht. Dank Ihres Kommentars konnte ich herausfinden, dass ich die depends_onAussage überall dort aktualisieren sollte , wo sie sich auf diese App bezieht. Dies ist wirklich die beste Antwort hier. Vielen Dank! :)
Manu
55

Dank der Antworten von Dominique Guardiola und Kochfeldern konnte ich ein schwieriges Problem lösen. Es gibt jedoch einige Probleme mit der Lösung. Hier ist meine Meinung dazu.

Die Verwendung manage.py reset southist keine gute Idee, wenn Sie Apps von Drittanbietern haben , die beispielsweise South verwenden django-cms(im Grunde verwendet alles South).

reset south löscht den gesamten Migrationsverlauf für alle von Ihnen installierten Apps.

Bedenken Sie nun, dass Sie auf die neueste Version von aktualisieren django-cms, es wird neue Migrationen wie enthalten 0009_do_something.py. Süd wird sicherlich verwirrt werden , wenn Sie versuchen , dass die Migration zu laufen , ohne dass 0001durch 0008die Migrationsgeschichte.

Es ist viel besser / sicherer, nur die Apps, die Sie warten , selektiv zurückzusetzen .


Stellen Sie zunächst sicher, dass Ihre Apps zwischen Migrationen auf der Festplatte und Migrationen, die in der Datenbank ausgeführt wurden, keine Desynchronisierung aufweisen. Andernfalls treten Kopfschmerzen auf.

1. Löschen Sie den Migrationsverlauf für meine Apps

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

2. Löschen Sie Migrationen für meine Apps

$ rm -rf my_app/migrations/

3. Erstellen Sie neue erste Migrationen für meine Apps

$ ./manage.py schemamigration --initial my_app

4. Führen Sie die ersten Migrationen für meine Apps fälschlicherweise aus

Dadurch werden die Migrationen eingefügt, south_migrationhistoryohne die tatsächlichen Tabellen zu berühren:

$ ./manage.py migrate --fake my_app

Schritt 3 und 4 sind eigentlich nur eine längere Variante von manage.py convert_to_south my_app, aber ich bevorzuge diese zusätzliche Kontrolle in solch heiklen Situationen wie dem Ändern der Produktionsdatenbank.

Knie
quelle
2
Ich habe meine Antwort bearbeitet, um Korrekturen für die gefundenen Probleme aufzunehmen (nur anhand Ihrer Antwort erraten) und sie in einer Produktionsdatenbank mit Millionen von Zeilen getestet.
Kochfelder
2
Das ist ziemlich genau das, was wir tun. Wenn Sie in Schritt 4 die Option --delete-ghost-migrations verwenden, können Sie Schritt 1
weglassen.
Sie sollten die App-Namen explizit in angeben, ./manage.py migrate --fakewenn Sie keine Migration anderer Apps fälschen möchten, für die Migrationen ausstehen.
Wadim
2
@wadim Daher Schritt 0: "Stellen Sie sicher, dass zwischen Migrationen auf der Festplatte und Migrationen, die in der Datenbank ausgeführt wurden, keine Desynchronisierung besteht."
Knie
@thnee Richtig. Es ist wahrscheinlich erwähnenswert, dass Sie sich in Schritt 0 auf alle installierten Apps beziehen. Kennen Sie eine einfache Möglichkeit, Schritt 0 auszuführen?
Wadim
7

Wie bei Thnee (siehe ihre Antwort) verwenden wir einen sanfteren Ansatz für den hier zitierten Vorschlag des Südautors (Andrew Godwin) und trennen während der Bereitstellung, was wir mit der Codebasis tun, von dem, was wir mit der Datenbank tun , weil die Bereitstellungen wiederholbar sein müssen:

Was wir im Code tun:

# 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

Was machen wir mit der Datenbank, sobald dieser Code bereitgestellt ist?

# Fake the migration history, wiping out the rest
$ ./manage.py migrate appname --fake --delete-ghost-migrations
tobych
quelle
Ich glaube, ich habe genau das Gleiche getan, aber Datenbankeinträge manuell gelöscht, anstatt --delete_ghoist-migrations zu verwenden. Dein Weg ist ein bisschen schöner.
Wobbily_col
1

Wenn Sie nur an der Entwicklungsmaschine arbeiten, habe ich einen Verwaltungsbefehl geschrieben, der ziemlich genau das tut, was Dominique vorgeschlagen hat.

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

Im Gegensatz zum Vorschlag des südlichen Autors wird dies andere installierte Apps, die den Süden verwenden, NICHT SCHÄDIGEN.

idanzalz
quelle
Und wenn, anders als der Autor, Sie wollen bleiben Migrationen bestehende (dh wollen Sie die App sowie Migrationsgeschichte zurückzustellen, aber halten die aktuellen Migrationen), dann können Sie versuchen , dieses: goo.gl/0ZnWm
mgalgs
1

Das Folgende ist nur, wenn Sie alle Apps zurücksetzen möchten. Bitte sichern Sie alle Datenbanken vor dieser Arbeit. Notieren Sie auch Ihre abhängigen_on in den Anfangsdateien, falls vorhanden.

Einmal:

(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]

Testen Sie das Bootstrapping Ihres Projekts vor dem Push. Wenden Sie dann für jeden lokalen / Remote-Computer Folgendes an:

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

Führen Sie für jede App, die Sie erneut einbeziehen möchten, die Initiale (3) aus . Beachten Sie, dass durch Zurücksetzen (6) nur der Migrationsverlauf gelöscht wird, was für Bibliotheken nicht schädlich ist. Durch gefälschte Migrationen (7) wird der Migrationsverlauf aller installierten Apps von Drittanbietern wiederhergestellt.

yasc
quelle
0

Löschen Sie die erforderliche Datei aus dem App-Ordner

Instanzpfad

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

Wiki -ist meine App

Andrei Eremchuk
quelle