Ich habe eine Django-App mit vier Modellen. Mir ist jetzt klar, dass eines dieser Modelle in einer separaten App sein sollte. Ich habe South für Migrationen installiert, aber ich glaube nicht, dass dies automatisch erledigt werden kann. Wie kann ich eines der Modelle aus der alten App in ein neues migrieren?
Denken Sie auch daran, dass dies ein wiederholbarer Prozess sein muss, damit ich das Produktionssystem und dergleichen migrieren kann.
django
migration
django-south
Apreche
quelle
quelle
Antworten:
Wie man mit Süden migriert.
Nehmen wir an, wir haben zwei Apps: allgemein und spezifisch:
Jetzt möchten wir das Modell common.models.cat in eine bestimmte App verschieben (genau in bestimmte.models.cat). Nehmen Sie zuerst die Änderungen im Quellcode vor und führen Sie dann Folgendes aus:
Jetzt müssen wir beide Migrationsdateien bearbeiten:
Jetzt sind sich beide Apps-Migrationen der Veränderung bewusst und das Leben ist nur ein bisschen weniger schlecht :-) Das Festlegen dieser Beziehung zwischen Migrationen ist der Schlüssel zum Erfolg. Wenn Sie dies tun:
wird sowohl Migration als auch durchführen
wird Dinge nach unten migrieren.
Beachten Sie, dass ich für das Upgrade des Schemas eine allgemeine App und für das Downgrade eine bestimmte App verwendet habe. Das liegt daran, wie die Abhängigkeit hier funktioniert.
quelle
orm['contenttypes.contenttype'].objects.filter
Linie im rückwärtigen Teil von geben0003_create_cat
? Auch ich möchte einen Tipp teilen. Wenn Sie Indizes haben, müssen diese ebenfalls geändert werden. In meinem Fall handelte es sich um eindeutige Indizes, daher sieht mein Forward wie folgt aus:db.delete_unique('common_cat', ['col1'])
db.rename_table('common_cat', 'specific_cat')
db.delete_unique('specific_cat', ['col1'])
orm['contenttypes.contenttype']
, müssen Sie--freeze contenttypes
Ihrenschemamigration
Befehlen auch die Option hinzufügen .python manage.py schemamigration specific create_cat --auto --freeze common
, um über eine gemeinsame App auf das Katzenmodell zuzugreifen.Um bauen auf Potr Czachur ‚s Antwort , Situationen , die Foreign einzubeziehen sind komplizierter und sollte etwas anders gehandhabt werden.
(Das folgende Beispiel baut auf den
common
undspecific
Apps auf, auf die in der aktuellen Antwort verwiesen wird.)würde dann zu ändern
Laufen
würde die folgenden Migrationen generieren (ich ignoriere absichtlich Django ContentType-Änderungen - siehe Antwort, auf die zuvor verwiesen wurde, um damit umzugehen):
Wie Sie sehen können, muss der FK geändert werden, um auf die neue Tabelle zu verweisen. Wir müssen eine Abhängigkeit hinzufügen, damit wir die Reihenfolge kennen, in der die Migrationen angewendet werden (und damit die Tabelle vorhanden ist, bevor wir versuchen, eine FK hinzuzufügen), aber wir müssen auch sicherstellen, dass das Zurückrollen auch funktioniert, da die Die Abhängigkeit gilt in umgekehrter Richtung .
Per der Dokumentation Süd ,
depends_on
wird sichergestellt , dass0004_auto__add_cat
läuft , bevor Sie0009_auto__del_cat
bei der Migration nach vorn , aber in der umgekehrten Reihenfolge beim Rückwärts Migration . Wenn wirdb.rename_table('specific_cat', 'common_cat')
dasspecific
Rollback belassen ,common
schlägt das Rollback fehl, wenn versucht wird, den ForeignKey zu migrieren, da die Tabelle, auf die die Tabelle verweist, nicht vorhanden wäre.Hoffentlich ist dies näher an einer "realen" Situation als die vorhandenen Lösungen, und jemand wird dies hilfreich finden. Prost!
quelle
Modelle sind nicht sehr eng mit Apps verbunden, daher ist das Verschieben ziemlich einfach. Django verwendet den App-Namen im Namen der Datenbanktabelle. Wenn Sie also Ihre App verschieben möchten, können Sie die Datenbanktabelle entweder über eine SQL-
ALTER TABLE
Anweisung umbenennen oder - noch einfacher - einfach dendb_table
Parameter in derMeta
Klasse Ihres Modells verwenden , um auf die zu verweisen alte Bezeichnung.Wenn Sie bisher irgendwo in Ihrem Code ContentTypes oder generische Relationen verwendet haben, möchten Sie wahrscheinlich
app_label
den Content-Typ umbenennen, der auf das sich bewegende Modell verweist, damit vorhandene Relationen erhalten bleiben.Wenn Sie überhaupt keine Daten zum Speichern haben, ist es natürlich am einfachsten, die Datenbanktabellen vollständig zu löschen und
./manage.py syncdb
erneut auszuführen .quelle
Hier ist eine weitere Lösung für Potrs hervorragende Lösung. Fügen Sie Folgendes zu bestimmten / 0003_create_cat hinzu
Wenn diese Abhängigkeit nicht festgelegt ist, kann South nicht garantieren, dass die
common_cat
Tabelle zum Zeitpunkt der Ausführung von spezifischem / 0003_create_cat vorhanden ist, und wirft einendjango.db.utils.OperationalError: no such table: common_cat
Fehler auf Sie.South führt Migrationen in lexikografischer Reihenfolge durch, sofern die Abhängigkeit nicht explizit festgelegt ist. Da
common
vor kommtspecific
allcommon
Migrationen s‘würde , bevor Tabelle Umbenennung laufen lassen, so wäre es wahrscheinlich nicht im ursprünglichen Beispiel durch Potr gezeigt reproduzieren. Aber wenn Sie umbenennencommon
zuapp2
undspecific
zuapp1
werden Sie in dieses Problem.quelle
Der Prozess, auf den ich mich derzeit festgelegt habe, seit ich ein paar Mal hier war und beschlossen habe, ihn zu formalisieren.
Dies wurde ursprünglich gebaut auf Potr Czachur Antwort und Matt Briançon Antwort , mit Süd 0.8.4
Schritt 1. Ermitteln Sie untergeordnete Fremdschlüsselbeziehungen
In diesem erweiterten Fall haben wir ein anderes verwandtes Modell entdeckt, wie:
Schritt 2. Erstellen Sie Migrationen
Schritt 3. Quellcodeverwaltung: Bisherige Änderungen festschreiben.
Dies macht den Vorgang wiederholbarer, wenn Sie auf Zusammenführungskonflikte stoßen, z. B. wenn Teamkollegen Migrationen auf die aktualisierten Apps schreiben.
Schritt 4. Fügen Sie Abhängigkeiten zwischen den Migrationen hinzu.
Grundsätzlich
create_kittycat
hängt es vom aktuellen Zustand von allem ab, und dann hängt alles davon abcreate_kittycat
.Schritt 5. Die Änderung zum Umbenennen der Tabelle, die wir vornehmen möchten.
Schritt 6. Nur wenn Sie backwards () benötigen, um zu arbeiten UND einen KeyError rückwärts laufen zu lassen.
Schritt 7. Testen Sie es - was für mich funktioniert, reicht möglicherweise nicht für Ihre reale Lebenssituation aus :)
quelle
Die Verwendung der ursprünglichen Antwort von @Potr oben funktionierte für mich unter South 0.8.1 und Django 1.5.1 nicht. Ich poste unten, was für mich funktioniert hat, in der Hoffnung, dass es für andere hilfreich ist.
quelle
Ich werde eine explizitere Version eines der Dinge geben, die Daniel Roseman in seiner Antwort vorgeschlagen hat ...
Wenn Sie nur das
db_table
Meta-Attribut des Modells ändern, das Sie verschoben haben, um auf den vorhandenen Tabellennamen zu verweisen (anstelle des neuen Namens, den Django ihm geben würde, wenn Sie ihn fallen lassen und a ausführensyncdb
), können Sie komplizierte Südmigrationen vermeiden. z.B:Original:
Nach dem Umzug:
Jetzt müssen Sie nur noch eine Datenmigration durchführen, um das
app_label
forMyModel
in derdjango_content_type
Tabelle zu aktualisieren, und schon kann es losgehen ...Führen Sie
./manage.py datamigration django update_content_type
die von South für Sie erstellte Datei aus und bearbeiten Sie sie:quelle