HOWTO · Django
Rollback der letzten Datenbankmigration in Django
In diesem Artikel erfahren Sie, wie Sie in Django zur letzten Datenbankmigration zurückkehren können.
Auf dieser Seite
Um die zuletzt angewendete Django-Migration rückgängig zu machen, führen Sie python manage.py migrate <app_label> <migration_name> aus. Wählen Sie dabei die Migration, die weiterhin angewendet bleiben soll – normalerweise diejenige unmittelbar vor der Migration, die Sie zurücknehmen möchten. Django kehrt die Migrationen der angegebenen App zurück, die nach diesem Ziel liegen. Prüfen Sie zuerst mit showmigrations den aktuellen Status der App. Sichern Sie wichtige Daten, bevor Sie eine Migration zurücknehmen: Beim Rückgängigmachen von Schemaänderungen können Daten verloren gehen, und manche Vorgänge lassen sich überhaupt nicht umkehren.
Zu einer bestimmten Migration zurückkehren
Mit python manage.py showmigrations <app_label> können Sie die Migrationen einer App auflisten. Angewendete Migrationen sind mit [X] markiert, noch nicht angewendete mit [ ]. Das App-Label ist der Django-Anwendungsname, der in Migrationsbefehlen verwendet wird. Der Migrationsname ist der Dateiname ohne .py.
Angenommen, die App blog hat die Migrationen 0001_initial, 0002_add_author und 0003_remove_legacy_field, und alle drei wurden angewendet. Um nur 0003_remove_legacy_field rückgängig zu machen, geben Sie 0002_add_author als Ziel an: python manage.py migrate blog 0002_add_author. Das Ziel bezeichnet den Migrationsstand, der erhalten bleiben soll, und nicht die Migration, die zurückgenommen werden soll. Django kehrt 0003 und alle späteren angewendeten Migrationen der App blog zurück. Eine Nummer wie 0002 kann als Ziel genügen; der vollständige Name macht die Auswahl jedoch eindeutig.
Führen Sie den Befehl in der Projektumgebung aus, in der manage.py die richtigen Einstellungen und die richtige Datenbankverbindung laden kann. Prüfen Sie vor dem Fortfahren, ob App und Datenbank stimmen – besonders, wenn mehrere Umgebungen eingerichtet sind.
Führen Sie dieses Python-Snippet aus, um einen Befehl für eine App und ein Ziel auszugeben:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
app_label = "blog"
target = "0002_add_author"
print(f"python manage.py migrate {app_label} {target}")
python manage.py migrate blog 0002_add_author
Der Code sowie die darin angezeigten Bezeichnungen und Ausgaben bleiben auf Englisch. Das Snippet formatiert lediglich den Befehl. Führen Sie den ausgegebenen Befehl in Ihrem Django-Projekt aus, um den Datenbankstatus zu ändern.
Alle Migrationen einer App zurücknehmen
Um alle angewendeten Migrationen einer App rückgängig zu machen, verwenden Sie python manage.py migrate <app_label> zero, zum Beispiel python manage.py migrate blog zero. zero bezeichnet den Zielzustand, in dem für diese App noch keine Migrationen angewendet wurden. Django kehrt den Migrationsverlauf der App in umgekehrter Reihenfolge zurück. Das bedeutet nicht einfach, dass nur die letzte Migration rückgängig gemacht wird. Dabei können Tabellen, Spalten und die darin gespeicherten Daten entfernt werden. Prüfen Sie die Migrationsliste der App und sichern Sie die Datenbank, bevor Sie dieses Ziel verwenden.
Wenn Sie mehrere, aber nicht alle Migrationen zurücknehmen möchten, geben Sie eine frühere Migration als Ziel an. Django arbeitet vom derzeit angewendeten Stand zurück, bis es dieses Ziel erreicht. Migrationen anderer Apps werden nicht allein deshalb ausgewählt, weil sie im gesamten Projektverlauf später liegen; Abhängigkeiten können den Ausführungsplan jedoch beeinflussen. Lesen Sie Djangos geplante Vorgänge, bevor Sie eine Änderung in der Produktionsumgebung bestätigen.
Umkehrbarkeit und Datenverlust verstehen
Django kann einen Vorgang rückgängig machen, wenn die Migration eine Umkehroperation definiert oder Django eine solche ableiten kann. Manche Vorgänge lassen sich nicht wiederherstellen, etwa das Löschen von Daten durch eine benutzerdefinierte Python-Operation ohne Umkehrfunktion. Beim Versuch, eine solche Migration zurückzunehmen, wird IrreversibleError ausgelöst. Prüfen Sie die Vorgänge der Migration und die vollständige Fehlermeldung, um den Schritt ohne Umkehrmöglichkeit zu finden. Gehen Sie nicht davon aus, dass das Wiederherstellen einer älteren Migrationsdatei die Auswirkungen auf die Datenbank umkehrbar macht.
Auch bei einer umkehrbaren Schemaänderung können Daten verloren gehen. Wird beispielsweise das Entfernen eines Felds rückgängig gemacht, lassen sich Werte, die beim Entfernen des Felds verworfen wurden, dadurch nicht wiederherstellen. Erstellen Sie vor dem Zurücknehmen einer Migration eine Datenbanksicherung, prüfen Sie, ob Schreibzugriffe der Anwendung pausiert werden müssen, und wägen Sie ab, ob eine Vorwärtskorrektur sicherer wäre. Spielen Sie das Vorgehen in der Produktionsumgebung zunächst anhand einer aktuellen Sicherung durch und prüfen Sie den Wiederherstellungsplan, bevor Sie die Live-Datenbank ändern.
Git verwaltet die Quelldateien der Migrationen, während migrate den Datenbankstatus ändert. Das Auschecken oder Zurücksetzen eines Git-Commits macht eine Datenbankmigration nicht von selbst rückgängig. Werden Migrationsdateien unabhängig davon wiederhergestellt, kann außerdem der Code vom in der Datenbank gespeicherten Migrationsverlauf abweichen. Verwenden Sie daher für Datenbankänderungen Djangos Migrationsbefehle und stimmen Sie eine Wiederherstellung des Codes separat ab.
Datenbankstatus überprüfen
Führen Sie nach Abschluss des Befehls erneut python manage.py showmigrations <app_label> aus. Prüfen Sie, ob das gewünschte Ziel und frühere Migrationen mit [X] markiert sind und zurückgenommene Migrationen mit [ ]. Die Ausgabe zeigt Djangos gespeicherten Migrationsstatus. Sie bestätigt weder alle Erwartungen an die Anwendungsdaten noch, dass Schema und Daten fehlerfrei sind. Prüfen Sie das Verhalten der betroffenen Anwendung und untersuchen Sie bei Bedarf die Datenbank oder führen Sie projektspezifische Prüfungen aus.
Wenn die Markierungen nicht zum gewünschten Ziel passen, nehmen Sie keine weitere Migration zurück. Vergewissern Sie sich, dass Sie mit der vorgesehenen Datenbank verbunden sind, prüfen Sie die Befehlsausgabe und die Migrationsabhängigkeiten und entscheiden Sie anhand des tatsächlich gespeicherten Status über den nächsten Schritt.