Wie vereinfache ich Migrationen in Django 1.7?


92

Es gibt bereits ähnliche Fragen für South, aber ich habe mein Projekt mit Django 1.7 gestartet und benutze South nicht.

Während der Entwicklung wurden viele Migrationen erstellt, die Software wurde jedoch noch nicht ausgeliefert und es gibt keine Datenbank, die migriert werden muss. Daher möchte ich die Migrationen zurücksetzen, als ob mein aktuelles Modell das ursprüngliche wäre, und alle Datenbanken neu erstellen.

Was ist der empfohlene Weg, um das zu tun?

EDIT: Ab Django 1.8 gibt es einen neuen Befehl namens squashmigrations, der das hier beschriebene Problem mehr oder weniger löst.


Was bedeutet es, eine Migration zurückzusetzen? Mache es Rückgängig?
Ciro Santilli 13 冠状 病 六四 事件 13

Antworten:


137

Ich schaff das. Ich habe das gerade herausgefunden und es ist gut.

  • Um die Migrationstabelle zu löschen:

    ./manage.py migrate --fake <app-name> zero
  • app-name/migrations/Ordner oder Inhalt entfernen .

  • Machen Sie die Migrationen:

    ./manage.py makemigrations <app-name>
  • Räumen Sie Ihre Migrationen schließlich auf, ohne andere Datenbankänderungen vorzunehmen:

    ./manage.py migrate --fake <app-name>

5
Das ist eine gute Antwort. Das Löschen der Migrationen macht keinen Schaden rückgängig, den fehlerhafte Migrationen angerichtet haben. Dies reinigt tatsächlich den Schiefer und lässt Sie von vorne beginnen.
Rogueleaderr

15
Wenn Sie etwas näher darauf eingehen möchten, sollte dies die akzeptierte Antwort sein.
Tani-Rokk

8
Großartige einzeilige Antwort, Bruder, ich habe keine Ahnung, was dies bewirkt
bischoffingston

13
Diese Zeile kehrt Migrationen einfach nacheinander um, bis zero. Für Django Migrationssystem <app-name> ist jetzt eine neue App und makemigrations <app-name>startet ab 0001. --fakeverhindert, dass Tabellen tatsächlich geändert werden, sodass Migrationen nur als umgekehrt markiert und nicht tatsächlich auf das Schema angewendet werden sollten. (Der Vollständigkeit halber kleine Erklärungen hinzufügen, @ tani-rokk, @Fabrizio)
Mir Nazim

17
manage.py migrate --fake <app-name> zeroUm die Migrationstabelle zu löschen, entfernen Sie dann <App-Name> / migrations / Ordner oder Inhalt. Dann manage.py makemigrations <app-name>und endlich manage.py migrate --fake <app-name>. Dadurch werden Ihre Migrationen aufgeräumt, ohne dass andere Datenbankänderungen vorgenommen werden müssen.
Doeke

36

In der Django 1.7-Version von Migrationen wurde die Reset-Funktionalität, die sich früher in South befand, zugunsten neuer Funktionen zum "Squashing" Ihrer Migrationen eingestellt. Dies soll ein guter Weg sein, um die Anzahl der Migrationen in Schach zu halten.

https://docs.djangoproject.com/de/dev/topics/migrations/#squashing-migrations

Wenn Sie immer noch wirklich von vorne anfangen möchten, können Sie die Migrationstabelle möglicherweise leeren und die Migrationen entfernen, nach denen Sie sie makemigrationserneut ausführen würden.


2
Wie würde ich "die Migrationen entfernen", außer die Migrationstabelle zu leeren? Würde ich den gesamten Ordner oder nur die 00X _ *. Py-Dateien entfernen?
Kit Fisto

Mit South können Sie den Migrationsordner entfernen, der neu erstellt wird, wenn Sie makemigrations erneut ausführen. Ich
gehe

4
Nur eine Notiz. Wenn Sie in Django 1.7 den Migrationsordner nicht sorgfältig löschen, kann dies eine Ausnahme auslösen, wenn Ihr Modell ein Kind eines anderen istraise KeyError("Migration %s dependencies reference nonexistent parent node %r" % (migration, parent))
Algorithmatic

Insbesondere ./manage.py squashmigrations myapp 0004werden alle Migrationen vor der Migration 0004in Ihrer Anwendung gequetscht myapp. Dadurch wird eine einzelne gequetschte Migration erstellt.
Bryce Guinta

22

Ich hatte gerade das gleiche Problem. Hier ist meine Problemumgehung.

#!/bin/sh
echo "Starting ..."

echo ">> Deleting old migrations"
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
find . -path "*/migrations/*.pyc"  -delete


# Optional
echo ">> Deleting database"
find . -name "db.sqlite3" -delete

echo ">> Running manage.py makemigrations"
python manage.py makemigrations

echo ">> Running manage.py migrate"
python manage.py migrate

echo ">> Done"

Der findBefehl: http://unixhelp.ed.ac.uk/CGI/man-cgi?find


13
Dies löscht die Daten, nicht nur die Migrationen
Kochfelder

2
Sie sollten auch .pyc-Dateien löschen
shalbafzadeh

7

Angenommen, dies ist Ihre Projektstruktur.

project_root/
    app1/
        migrations/
    app2/
        migrations/
    ...
    manage.py
    remove_migrations.py

Sie können das Skript remove_migrations.py an der oben angegebenen Stelle ausführen, um alle Migrationsdateien zu löschen.

#remove_migrations.py
"""
Run this file from a Django =1.7 project root. 
Removes all migration files from all apps in a project.
""" 
from unipath import Path

this_file = Path(__file__).absolute()
current_dir = this_file.parent
dir_list = current_dir.listdir()

for paths in dir_list:
    migration_folder = paths.child('migrations')
    if migration_folder.exists():
        list_files = migration_folder.listdir()
        for files in list_files:
            split = files.components()
            if split[-1] != Path('__init__.py'):
                files.remove()

Das manuelle Löschen kann anstrengend sein, wenn Sie ein aufwendiges Projekt haben. Das hat mir viel Zeit gespart. Das Löschen von Migrationsdateien ist sicher. Ich habe dies ein x-tes Mal ohne Probleme getan ... bis jetzt.

Wenn ich jedoch den Migrationsordner gelöscht makemigrationsoder migrateden Ordner nicht für mich erstellt habe. Das Skript stellt sicher, dass der Migrationsordner mit seinen __init__.pySpeicherorten gespeichert bleibt, und löscht nur die Migrationsdateien.


Sie können einfach die Migrationsordner löschen und sie mit einer leeren Init .py (z. B. touch migrations/__init__.py) neu erstellen
Kochfelder

6
  1. Dateien löschen: delete_migrations.py (im Stammverzeichnis von prj):
import os

for root, dirs, files in os.walk(".", topdown=False):
  for name in files:
      if '/migrations' in root and name != '__init__.py':
          os.remove(os.path.join(root, name))
  1. DELETE FROM django_migrations Where app in ('app1', 'app2');

  2. ./manage.py makemigrations

  3. ./manage.py migrate --fake

ODER Sie können eine Migration von all dem schreiben


Ich musste die App-Namen angeben ./manage.py makemigrations, damit es funktioniert:./manage.py makemigrations orders alerts
Salami

4

Ich probiere verschiedene Befehle aus und einige der Antworten helfen mir. Nur diese Sequenz hat in meinem Fall sowohl fehlerhafte Abhängigkeiten bei Migrationen in MYAPP behoben als auch alle früheren Migrationen von Grund auf neu bereinigt.

Stellen Sie zuvor sicher, dass die Datenbank bereits synchronisiert ist (z. B. fügen Sie hier kein neues Modellfeld hinzu oder ändern Sie die Metaoptionen).

rm -Rf MYAPP/migrations/*
python manage.py makemigrations --empty MYAPP
python manage.py makemigrations
python manage.py migrate --fake MYAPP 0002

Dabei ist 0002 die Migrationsnummer, die vom letzten Befehl makemigrations zurückgegeben wurde.

Jetzt können Sie makemigrations / migrate wieder normal ausführen, da die Migration 0002 gespeichert ist, sich jedoch nicht in der bereits synchronisierten Datenbank widerspiegelt.


Von allen oben genannten Lösungen funktionierte nur dies für mich ohne Probleme und ohne Löschen der Datenbank.
Vivek Jha

3

Wenn Sie sich nicht für frühere Migrationen interessieren, können Sie einfach alle Migrationen im Verzeichnis migrations / entfernen. Sie starten die Migrationssequenz von vorne und nehmen Ihr aktuelles Modell als Referenz, als hätten Sie jetzt das gesamte Modell geschrieben.

Wenn Sie mir nicht genug vertrauen, um sie zu entfernen, versuchen Sie stattdessen, sie zu entfernen.


Welche Bedeutung hat es, alte Migrationen beizubehalten? Meine Fragen kommen auf den Punkt, wenn man versucht, ein Upgrade von Django 1.6 auf 1.8 durchzuführen.
Jay Modi

Migrationen sind lediglich eine Erfolgsbilanz der Änderungen, die Sie an der Datenbank vorgenommen haben. Ich habe den Rat von vokiman mehr als einmal befolgt, wenn meine Migrationskette nicht mehr funktioniert.
Adam Starrh

1

Ein einfacher Weg ist

Gehen Sie zu jeder App und löschen Sie die Migrationsdateien.

Gehen Sie dann zur Tabelle django-migrtaions in der Datenbank und schneiden Sie sie ab (löschen Sie alle Einträge).

Danach können Sie erneut Migrationen erstellen.


1
Stellen Sie beim Löschen von Migrationsdateien sicher, dass Sie die Init- Dateien nicht löschen .
Sprksh

Das hat mir wirklich geholfen. Ich habe alle Migrationen gelöscht, die Tabellen aus meiner SQLite-Datenbank gelöscht, konnte aber immer noch keine Migrationen durchführen. Nachdem ich jedoch die _init_ .py-Dateien (doh) wiederhergestellt hatte , konnte ich die Migrationen erneut durchführen und loslegen. @sprksh = Lebensretter!
Twknab

0

CD in das src-Verzeichnis cd /path/to/src

Migrationsverzeichnisse löschen rm -rf your_app/migrations/

Beachten Sie, dass dies für jede App separat erfolgen sollte

Wandern python3.3 manage.py migrate

wenn Sie erneut beginnen möchten python3.3 manage.py makemigrations your_app


0

Wenn Sie sich im Entwicklungsmodus befinden und einfach alles zurücksetzen möchten (Datenbank, Migrationen usw.), verwende ich dieses Skript basierend auf der Antwort von Abdelhamid Ba. Dadurch werden die Tabellen der Datenbank (Postgres) gelöscht, alle Migrationsdateien gelöscht, die Migrationen erneut ausgeführt und meine ersten Geräte geladen:

#!/usr/bin/env bash
echo "This will wipe out the database, delete migration files, make and apply migrations and load the intial fixtures."

while true; do
    read -p "Do you wish to continue?" yn
    case $yn in
        [Yy]* ) make install; break;;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac
done

echo ">> Deleting old migrations"
find ../../src -path "*/migrations/*.py" -not -name "__init__.py" -delete

# Optional
echo ">> Deleting database"
psql -U db_user -d db_name -a -f ./reset-db.sql

echo ">> Running manage.py makemigrations and migrate"
./migrations.sh

echo ">> Loading initial fixtures"
./load_initial_fixtures.sh

echo ">> Done"

reset-db.sql Datei:

DO $$ DECLARE
    r RECORD;
BEGIN
    -- if the schema you operate on is not "current", you will want to
    -- replace current_schema() in query with 'schematodeletetablesfrom'
    -- *and* update the generate 'DROP...' accordingly.
    FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
        EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
    END LOOP;
END $$;

Datei migration.sh:

#!/usr/bin/env bash
cd ../../src
./manage.py makemigrations
./manage.py migrate

Datei load_initial_fixtures.sh:

#!/usr/bin/env bash
cd ../../src
./manage.py loaddata ~/path-to-fixture/fixture.json

Stellen Sie einfach sicher, dass Sie die Pfade so ändern, dass sie Ihrer App entsprechen. Ich persönlich habe diese Skripte in einem Ordner namens project_root / script / local, und die Quellen von django befinden sich in project_root / src.


0

Nachdem ich jeden "Migrations" -Ordner in meiner App (manuell) gelöscht hatte, führte ich Folgendes aus:

./manage.py dbshell
delete from django_migrations;

Dann dachte ich, ich könnte einfach alles tun ./manage.py makemigrations, um sie alle zu regenerieren. Es wurden jedoch keine Änderungen festgestellt. Ich habe dann versucht , eine App zu einem Zeitpunkt festgelegt wird : ./manage.py makemigrations foo,./manage.py makemigrations bar . Dies führte jedoch zu zirkulären Abhängigkeiten, die nicht aufgelöst werden konnten.

Schließlich habe ich einen einzelnen Makemigrations-Befehl ausgeführt, der ALLE meine Apps angegeben hat (in keiner bestimmten Reihenfolge):

./manage.py makemigrations foo bar bike orange banana etc

Diesmal hat es funktioniert - zirkuläre Abhängigkeiten wurden automatisch aufgelöst (es wurden bei Bedarf zusätzliche Migrationsdateien erstellt).

Dann konnte ich rennen ./manage.py migrate --fakeund war wieder im Geschäft.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.