it-swarm.com.de

django stellt die letzte Migration wieder her

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?

291
Ronen Ness

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
535
Alasdair

Die Antwort von Alasdair behandelt die Grundlagen

  • Identifizieren Sie die gewünschten Migrationen anhand von ./manage.py showmigrations.
  • migrate mit dem App-Namen und dem Migrationsnamen

Es 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/

So machen Sie eine No-Op-Umkehrung

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)

27
AlanSE

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.

8
sprksh

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.

6
Özer S.

Ich habe dies in 1.9.1 getan (um die letzte oder zuletzt erstellte Migration zu löschen):

  1. rm <appname>/migrations/<migration #>*

    Beispiel: rm myapp/migrations/0011*

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

5
MIkee

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

  • When: Dies ist ein Basismodell eines anderen Modells, das nur für die Modellvererbung erstellt wurde.
  • Lösung: Set class Meta: abstract = True

B) Die Tabelle wird selten, von etwas anderem oder manuell in besonderer Weise erstellt.

  • Lösung: Verwenden Sie class Meta: managed = False
    Die Migration wird erstellt, aber nur in Tests verwendet. Die Migrationsdatei ist wichtig, andernfalls können Datenbanktests nicht ausgeführt werden, beginnend mit dem reproduzierbaren Anfangszustand.

C) Die Tabelle wird nur auf bestimmten Maschinen verwendet (z. B. in der Entwicklung).

  • Lösung: Verschieben Sie das Modell in eine neue Anwendung, die nur unter besonderen Bedingungen zu INSTALLED_APPS hinzugefügt wird, oder verwenden Sie einen bedingten class Meta: managed = some_switch.

D) Das Projekt verwendet mehrere Datenbanken in settings.DATABASES

  • Lösung: Schreiben Sie einen Datenbank-Router mit der Methode 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.)

2
hynekcer

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.

0
Pransh Tiwari