Come semplificare le migrazioni in Django 1.7?


92

Ci sono già domande simili per South, ma ho iniziato il mio progetto con Django 1.7 e non sto usando South.

Durante lo sviluppo sono state create molte migrazioni, tuttavia il software non è ancora stato consegnato e non esiste alcun database da migrare. Pertanto vorrei resettare le migrazioni come se il mio modello attuale fosse quello originale e ricreare tutti i database.

Qual è il modo consigliato per farlo?

EDIT: A partire da Django 1.8 c'è un nuovo comando chiamato squashmigrations che risolve più o meno il problema qui descritto.


Cosa significa resettare una migrazione? Annullarlo?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Risposte:


137

Ho capito. L'ho appena capito ed è buono.

  • Innanzitutto, per cancellare la tabella delle migrazioni:

    ./manage.py migrate --fake <app-name> zero
  • Rimuovi app-name/migrations/cartella o contenuto.

  • Effettua le migrazioni:

    ./manage.py makemigrations <app-name>
  • Infine riordina le tue migrazioni senza apportare altre modifiche al database:

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

5
Questa è una buona risposta. La semplice eliminazione delle migrazioni non annulla i danni causati dalle migrazioni difettose. Questo in realtà pulisce la lavagna e ti consente di ricominciare da capo.
rogueleaderr

15
Se vuoi approfondire un po ', questa dovrebbe essere la risposta accettata.
tani-rokk

8
Grande risposta di una riga fratello, non ho idea di cosa faccia
bischoffingston il

13
Questa linea inverte semplicemente le migrazioni una per una, finché zero. Per il sistema di migrazioni Django, <app-name> ora è una nuova app e makemigrations <app-name>partirà da 0001. --fakeimpedisce che le tabelle vengano effettivamente modificate, che le migrazioni dovrebbero essere contrassegnate solo come invertite e non applicate allo schema. (Aggiungendo piccole spiegazioni per completezza, @ tani-rokk, @Fabrizio)
Mir Nazim

17
manage.py migrate --fake <app-name> zeroper cancellare la tabella delle migrazioni, quindi rimuovere <app-name> / migrations / cartella o contenuti. Poi manage.py makemigrations <app-name>e finalmente fallo manage.py migrate --fake <app-name>. Ciò consentirà di mettere ordine nelle migrazioni senza apportare altre modifiche al database.
doeke

36

Nella versione Django 1.7 delle migrazioni la funzionalità di ripristino che si trovava nel Sud è stata abbandonata a favore di nuove funzionalità per "schiacciare" le tue migrazioni. Questo dovrebbe essere un buon modo per tenere sotto controllo il numero di migrazioni.

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

Se vuoi ancora iniziare davvero da zero, presumo che tu possa ancora svuotare la tabella delle migrazioni e rimuovere le migrazioni, dopodiché dovresti eseguire di makemigrationsnuovo.


2
Come dovrei "rimuovere le migrazioni" oltre a svuotare la tabella delle migrazioni? Rimuoverei l'intera cartella o solo i file 00X _ *. Py?
Kit Fisto

con South è possibile rimuovere la cartella migrations che verrebbe ricreata quando si esegue nuovamente makemigrations. Presumo che
funzioni

4
Solo una nota. in Django 1.7, se, non con attenzione, elimini la cartella di migrazione potrebbe sollevare un'eccezione se il tuo modello è figlio di un altroraise KeyError("Migration %s dependencies reference nonexistent parent node %r" % (migration, parent))
Algorithmatic

In particolare, ./manage.py squashmigrations myapp 0004annullerà tutte le migrazioni prima della migrazione 0004nella tua applicazione myapp. Questo creerà una singola migrazione schiacciata.
Bryce Guinta

22

Ho appena avuto lo stesso problema. Ecco la mia soluzione alternativa.

#!/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"

Il findcomando: http://unixhelp.ed.ac.uk/CGI/man-cgi?find


13
questo cancella i dati, non solo le migrazioni
piani cottura

2
dovresti eliminare anche i file .pyc
shalbafzadeh

7

Supponendo che questa sia la struttura del tuo progetto,

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

puoi eseguire lo script remove_migrations.py dalla posizione sopra indicata per eliminare tutti i file di migrazione.

#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()

L'eliminazione manuale può essere stancante se hai un progetto elaborato. Questo mi ha fatto risparmiare molto tempo. L'eliminazione dei file di migrazione è sicura. L'ho fatto un'ennesima volta senza affrontare alcun problema ... ancora.

Tuttavia, quando ho eliminato la cartella delle migrazioni makemigrationso migratenon ho creato nuovamente la cartella per me. Lo script si assicura che la cartella di migrazione con i suoi __init__.pyrimanga, eliminando solo i file di migrazione.


potresti semplicemente eliminare le cartelle delle migrazioni e ricrearle con un init .py vuoto (ad esempio touch migrations/__init__.py)
hobs

6
  1. Elimina file: delete_migrations.py (nella radice di 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

OPPURE, puoi scrivere la migrazione da tutto questo


Ho dovuto specificare i nomi delle app perché ./manage.py makemigrationsfunzionasse, in questo modo:./manage.py makemigrations orders alerts
Salami

4

Provo diversi comandi e alcune delle risposte mi aiutano. Solo questa sequenza nel mio caso ha risolto entrambe le dipendenze interrotte nelle migrazioni in MYAPP e ha pulito tutte le migrazioni passate partendo da zero.

Prima di fare questo assicurati che il database sia già sincronizzato (es. Non aggiungere un nuovo campo Modello qui o cambiare le opzioni Meta).

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

Dove 0002 è il numero di migrazione restituito dall'ultimo comando makemigrations.

Ora puoi eseguire makemigrations / migrate di nuovo normalmente perché la migrazione 0002 è archiviata ma non riflessa nel database già sincronizzato.


Di tutte le soluzioni sopra menzionate, solo questa ha funzionato per me senza problemi e senza eliminare il database.
Vivek Jha

3

Se non ti interessano le migrazioni precedenti, che ne dici di rimuovere tutte le migrazioni nella directory migrations /? inizierai la sequenza di migrazione da zero, prendendo come riferimento il tuo modello attuale come se avessi scritto l'intero modello adesso.

Se non ti fidi abbastanza di me da rimuoverli, prova invece a spostarli.


Qual è il significato di mantenere vecchie migrazioni? Le mie domande colpiscono il terreno quando si cerca di aggiornare da django 1.6 a 1.8.
Jay Modi

Le migrazioni sono semplicemente un track record delle modifiche apportate al database. Ho seguito il consiglio di vokiman più di una volta quando la mia catena di migrazione smette di funzionare.
Adam Starrh

1

Un modo semplice è

Vai a ogni app ed elimina i file di migrazione.

Quindi vai alla tabella django-migrtaions nel database e troncala (elimina tutte le voci).

Dopodiché puoi creare nuovamente le migrazioni.


1
durante l'eliminazione dei file di migrazione, assicurati di non eliminare i file di inizializzazione .
sprksh

Questo mi ha davvero aiutato. Ho cancellato tutte le migrazioni, eliminato le tabelle dal mio DB sqlite, ma non ero ancora in grado di fare migrazioni ... tuttavia, una volta ripristinati i file _init_ .py (doh) sono stato in grado di fare di nuovo le migrazioni e iniziare a navigare. @sprksh = Lifesaver!
twknab

0

cd nella directory src cd /path/to/src

eliminare le directory di migrazione rm -rf your_app/migrations/

nota che questo dovrebbe essere fatto per ogni app separatamente

migrare python3.3 manage.py migrate

se desideri ricominciare python3.3 manage.py makemigrations your_app


0

Se sei in modalità sviluppo e vuoi solo ripristinare tutto (database, migrazioni, ecc.), Uso questo script basato sulla risposta di Abdelhamid Ba. Questo cancellerà le tabelle del database (Postgres), cancellerà tutti i file di migrazione, rieseguirà le migrazioni e caricherà i miei dispositivi iniziali:

#!/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"

file reset-db.sql:

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 $$;

file migration.sh:

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

file load_initial_fixtures.sh:

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

Assicurati solo di modificare i percorsi in modo che corrispondano alla tua app. Personalmente ho questi script in una cartella chiamata project_root / script / local, e i sorgenti di django sono in project_root / src.


0

Dopo aver eliminato ogni cartella "migrazioni" nella mia app (manualmente), ho eseguito:

./manage.py dbshell
delete from django_migrations;

Poi ho pensato che potevo fare solo ./manage.py makemigrationsper rigenerarli tutti. Tuttavia, non sono state rilevate modifiche. Ho quindi provato a specificare un'app alla volta: ./manage.py makemigrations foo, ./manage.py makemigrations bar. Tuttavia, ciò ha comportato dipendenze circolari che non è stato possibile risolvere.

Infine, ho eseguito un singolo comando makemigrations che specificava TUTTE le mie app (in nessun ordine particolare):

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

Questa volta ha funzionato: le dipendenze circolari sono state risolte automaticamente (ha creato file di migrazione aggiuntivi dove necessario).

Poi ho potuto correre ./manage.py migrate --fakee sono tornato in attività.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.