Ich habe eine Migration vorgenommen, die eine neue Tabelle hinzugefügt hat. Sie möchte sie wiederherstellen und die Migration löschen, ohne eine neue Migration zu erstellen.
Wie mache ich es? Gibt es einen Befehl zum Zurücksetzen der letzten Migration, und dann kann ich die Migrationsdatei einfach löschen?
Sie können durch die Migration zur vorherigen Migration zurückkehren.
Zum Beispiel, wenn Ihre letzten beiden Migrationen folgende sind:
0010_previous_migration
0011_migration_to_revert
Dann würden Sie tun:
./manage.py migrate my_app 0010_previous_migration
Sie können dann die Migration 0011_migration_to_revert
löschen.
Wenn Sie Django 1.8+ verwenden, können Sie die Namen aller Migrationen mit anzeigen
./manage.py showmigrations my_app
Um alle Migrationen für eine App umzukehren, können Sie Folgendes ausführen:
./manage.py migrate my_app zero
Die Antwort von Alasdair behandelt die Grundlagen
./manage.py showmigrations
.migrate
mit dem App-Namen und dem MigrationsnamenEs sei jedoch darauf hingewiesen, dass nicht alle Migrationen can rückgängig gemacht werden können. Dies geschieht, wenn Django keine Regel zum Umkehren hat. Bei den meisten Änderungen, die Sie automatisch mit ./manage.py makemigrations
vorgenommen haben, ist die Stornierung möglich. Benutzerdefinierte Skripts müssen jedoch sowohl vorwärts als auch rückwärts geschrieben sein, wie im Beispiel hier beschrieben:
https://docs.djangoproject.com/de/1.9/ref/migration-operations/
Wenn Sie eine RunPython
-Operation hatten, möchten Sie vielleicht nur die Migration rückgängig machen, ohne ein logisch strenges Umkehrskript zu schreiben. Der folgende Quick-Hack zu dem Beispiel aus den Dokumenten (obiger Link) ermöglicht dies, wobei die Datenbank in demselben Zustand bleibt, in dem sie sich nach der Migration befand, selbst nachdem sie rückgängig gemacht wurde.
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from Django.db import migrations, models
def forwards_func(apps, schema_editor):
# We get the model from the versioned app registry;
# if we directly import it, it'll be the wrong version
Country = apps.get_model("myapp", "Country")
db_alias = schema_editor.connection.alias
Country.objects.using(db_alias).bulk_create([
Country(name="USA", code="us"),
Country(name="France", code="fr"),
])
class Migration(migrations.Migration):
dependencies = []
operations = [
migrations.RunPython(forwards_func, lambda apps, schema_editor: None),
]
Dies funktioniert für Django 1.8, 1.9
Update: Eine bessere Schreibweise wäre, lambda apps, schema_editor: None
durch migrations.RunPython.noop
im obigen Snippet zu ersetzen. Beide sind funktional gleich. (Dank an die Kommentare)
Sie können auch die manuell erstellte Tabelle löschen.
Außerdem müssen Sie diese bestimmte Migrationsdatei löschen. Außerdem müssen Sie diesen bestimmten Eintrag in der Tabelle "Django-Migration" löschen (wahrscheinlich der letzte in Ihrem Fall), der mit dieser bestimmten Migration korreliert.
Hier ist meine Lösung, da die obige Lösung den Anwendungsfall nicht wirklich abdeckt, wenn Sie RunPython
verwenden.
Über den ORM können Sie mit auf die Tabelle zugreifen
from Django.db.migrations.recorder import MigrationRecorder
>>> MigrationRecorder.Migration.objects.all()
>>> MigrationRecorder.Migration.objects.latest('id')
Out[5]: <Migration: Migration 0050_auto_20170603_1814 for model>
>>> MigrationRecorder.Migration.objects.latest('id').delete()
Out[4]: (1, {u'migrations.Migration': 1})
So können Sie die Tabellen abfragen und die für Sie relevanten Einträge löschen. Auf diese Weise können Sie im Detail ändern. Bei RynPython
Migrationen müssen Sie sich auch um die Daten kümmern, die hinzugefügt/geändert/entfernt wurden. Das obige Beispiel zeigt nur, wie Sie über Djang ORM auf die Tabelle zugreifen.
Ich habe dies in 1.9.1 getan (um die letzte oder zuletzt erstellte Migration zu löschen):
rm <appname>/migrations/<migration #>*
Beispiel: rm myapp/migrations/0011*
in der Datenbank angemeldet und diese SQL ausgeführt (Postgres in diesem Beispiel)
delete from Django_migrations where name like '0011%';
Ich konnte dann neue Migrationen erstellen, die mit der gerade gelöschten Migrationsnummer (in diesem Fall 11) anfingen.
Der erste Teil, wie man "Migration rückgängig machen" macht, wurde von Alasdair beantwortet. Ich werde antworten:
... die Migration löschen, ohne eine neue Migration anzulegen?
TL; DR: Sie können ein paar zuletzt rückgängig gemachte (verwirrte) Migrationen löschen und nach dem Korrigieren von Modellen eine neue machen. Sie können mit anderen Mitteln einrichten, um so einzustellen, dass keine Tabelle mit dem Migrationsbefehl erstellt wird. Die letzte Migration muss jedoch so erstellt werden, dass sie den aktuellen Modellen entspricht.
Die "problematische" Migration, die eine unerwünschte Tabelle erstellt hat, wird durch eine neue Modellklasse verursacht, die Sie hinzugefügt haben.
Warum kann jemand keinen Tisch bekommen? Wie man es löst?
A) Keine Tabelle darf auf keiner Maschine und keinen Bedingungen vorhanden sein
class Meta: abstract = True
B) Die Tabelle wird selten, von etwas anderem oder manuell in besonderer Weise erstellt.
class Meta: managed = False
C) Die Tabelle wird nur auf bestimmten Maschinen verwendet (z. B. in der Entwicklung).
class Meta: managed = some_switch
.D) Das Projekt verwendet mehrere Datenbanken in settings.DATABASES
allow_migrate
, um die Datenbanken zu unterscheiden, in denen die Tabelle erstellt werden kann oder nicht.(Habe ich etwas vergessen? Ich gehe davon aus, dass alles andere für Sie funktioniert, nur die Tabelle sollte nicht erstellt werden. Dann kann beispielsweise ein Fehler in der Proxy-Option eines Modells ausgeschlossen werden.)
Die Migration wird in den Fällen B), C), D) mit Django 1.8 und in allen Fällen ABCD mit Django 1.9+ erstellt, jedoch nur in geeigneten Fällen auf die Datenbank angewendet oder möglicherweise niemals, wenn dies erforderlich ist. Seit Django 1.8 sind für die Durchführung von Tests Migrationen erforderlich. Der vollständige relevante aktuelle Status wird durch Migrationen aufgezeichnet, selbst wenn in Django 1.9+ Modelle mit managed = False erstellt werden, um einen ForeignKey zwischen verwalteten/nicht verwalteten Modellen erstellen zu können oder das Modell später als true verwalten zu lassen. (Diese Frage wurde zum Zeitpunkt von Django 1.8 Mainstream geschrieben. Alles hier sollte für Versionen zwischen 1.8 und 1.11 gelten.)
Wenn Sie beim Zurücksetzen der Migration auf Probleme stoßen und sie irgendwie durcheinander gebracht haben, können Sie fake
-Migrationen durchführen.
./manage.py migrate <name> --ignore-ghost-migrations --merge --fake
Bei der Django-Version <1.4 wird ein Eintrag in der south_migrationhistory
-Tabelle erstellt. Sie müssen diesen Eintrag löschen.
Jetzt können Sie die Migration problemlos rückgängig machen.
PS: Ich war lange Zeit festgefahren und führte gefälschte Migration durch und dann kam ich zurück.