Qual è l'approccio consigliato per ripristinare la cronologia delle migrazioni utilizzando Django South?


153

Ho accumulato parecchie migrazioni usando South (0.7) e Django (1.1.2) che stanno iniziando a consumare un bel po 'di tempo nei miei test unitari. Vorrei ripristinare la linea di base e iniziare una nuova serie di migrazioni. Ho esaminato la documentazione di South , fatto le consuete ricerche su Google / Stackoverflow (ad es. "Django south (resetta O cancella O rimuovi) cronologia migrazioni") e non ho trovato nulla di ovvio.

Un approccio che ho contemplato consisterebbe nel "ricominciare" rimuovendo "South" o "cancellando" manualmente la cronologia (ad esempio, cancellare la tabella db, rimuovere i file di migrazione dal direttore delle migrazioni) ed eseguire nuovamente,

./manage.py schemamigration southtut --initial

Quindi, se qualcuno lo ha già fatto e ha qualche consiglio / suggerimento, sarebbe molto apprezzato.


a volte è necessario aggiungere manualmente __init__.pyaappname/migrations
laike9m

2
Come reimpostare le migrazioni in 1.7 (con la migrazione integrata)?
Timo,

1
@Timo: docs.djangoproject.com/en/dev/topics/migrations/… potrebbe essere un approccio. Puoi anche rimuovere le tue migrazioni / directory e ripubblicarle, ./manage.py makemigrationsma succederanno cose brutte se non inizi da un nuovo db ...
Jocelyn delalande,

Penso che squashmigrationssia la risposta giusta
Julio Marins,

Risposte:


121

EDIT - Sto inserendo un commento qui sotto in cima a questo perché è importante leggerlo prima della> risposta accettata che segue @andybak

@Dominique: il tuo consiglio per quanto riguarda la gestione di reset del sud è pericoloso e potrebbe distruggere il database se nel progetto sono presenti app di terze parti che utilizzano sud, come sottolineato da @thnee di seguito. Dato che la tua risposta ha così tanti voti, la apprezzerei davvero se tu potessi modificarla e aggiungere almeno un avvertimento al riguardo, o (ancora meglio) cambiarlo per riflettere l'approccio @hobs (che è altrettanto conveniente, ma non lo fa influisce su altre app) - grazie! - chrisv, 26 marzo 13 alle 9:09

La risposta accettata è la seguente:

Innanzitutto, una risposta dell'autore del Sud :

Finché ti prendi cura di farlo su tutte le distribuzioni contemporaneamente, non ci dovrebbero essere problemi con questo. Personalmente, farei:

    rm -r appname/migrations/ 
    ./manage.py reset south 
    ./manage.py convert_to_south appname 

(Nota che la parte " reset south" cancella i record di migrazione per TUTTE le app, quindi assicurati di eseguire le altre due righe per tutte le app o di eliminare in modo selettivo).

La convert_to_southchiamata alla fine effettua una nuova migrazione e la applica in modo falso (poiché il database ha già le tabelle corrispondenti). Non è necessario eliminare tutte le tabelle delle app durante il processo.

Ecco cosa sto facendo sul mio server di produzione dev + quando devo liberarmi di tutte queste migrazioni di sviluppatori non necessarie:

  1. Assicurati di avere lo stesso schema DB su entrambi i lati
  2. elimina ogni cartella delle migrazioni su entrambi i lati
  3. run ./manage.py ripristina south (come dice il post) su entrambi i lati = cancella la tabella sud *
  4. eseguire ./manage.py convert_to_south su entrambi i lati (falsificazione della migrazione 0001)
  5. quindi posso riavviare per effettuare migrazioni e inviare le cartelle migrazioni sul mio server

* tranne se si desidera pulire solo un'app tra le altre, in tal caso è necessario modificare la tabella south_history ed eliminare solo le voci relative all'app.


2
Per la cronaca, la risposta dell'autore del Sud è stata la seguente: Fintanto che ti prendi cura di farlo su tutte le distribuzioni contemporaneamente, non ci dovrebbero essere problemi con questo. Personalmente, farei: rm -r nome app / migrations / ./manage.py ripristina sud ./manage.py convert_to_south nome app (nota che la parte "ripristina sud" cancella i record di migrazione per TUTTE le app, quindi assicurati di eseguire le altre due righe per tutte le app o elimina selettivamente).
Adriaan Tijsseling,

2
Si noti inoltre che se si eliminano le tabelle, è necessario manage.py schemamigration app name --initialinvece di convert_to_south.
Adriaan Tijsseling,

7
A partire da Django 1.5, il comando di gestione "reset" è sparito. Invece, ti consigliamo di fare qualcosa di simile south.models.MigrationHistory.objects.all().delete().
Andrew B.

13
@Dominique: i tuoi consigli in merito manage.py reset southsono pericolosi e potrebbero distruggere il database se nel progetto sono presenti app di terze parti che utilizzano south, come sottolineato da @thnee di seguito. Dato che la tua risposta ha così tanti voti, la apprezzerei davvero se tu potessi modificarla e aggiungere almeno un avvertimento al riguardo, o (ancora meglio) cambiarlo per riflettere l'approccio @hobs (che è altrettanto conveniente, ma non lo fa influenza altre app) - grazie!
chrisv,

3
Perché questo è stato così fortemente votato? Non dovresti quasi MAI eliminare completamente la tabella south_migrationhistory. Ciò rovinerebbe completamente qualsiasi app dipendente con migrazioni che non vuoi toccare. La risposta di Hob ​​è quella corretta.
Cerin,

188

Se devi reimpostare selettivamente (per una sola app) le migrazioni che richiedono troppo tempo, questo ha funzionato per me.

rm <app-dir>/migrations/*
python manage.py schemamigration <app-name> --initial
python manage.py migrate <app-name> 0001 --fake  --delete-ghost-migrations

Non dimenticare di ripristinare manualmente eventuali dipendenze da altre app aggiungendo righe come depends_on = (("<other_app_name>", "0001_initial"),("<yet_another_app_name>", "0001_initial"))al tuo <app-dir>/migrations/0001_initial.pyfile, come il primo attributo nella tua classe di migrazione appena sotto class Migration(SchemaMigration):.

È quindi possibile ./manage.py migrate <app-name> --fake --delete-ghost-migrationssu altri ambienti, per questa risposta SO . Ovviamente se falsi l'eliminazione o falsi migrate zero, dovrai eliminare manualmente tutte le tabelle db rimaste con una migrazione come questa .

Un'opzione più nucleare è ./manage.py migrate --fake --delete-ghost-migrationssul server di distribuzione live seguito da un [mio] sqldump. Quindi reindirizzare tale dump in [my] sql negli ambienti in cui è necessario il db migrato e completamente popolato. Il sacrilegio del sud, lo so, ma ha funzionato per me.


2
Quello che voglio veramente è "prendi modelle.pia come vangelo, e rendimi pulito da quel momento in poi". Mantenendo così la possibilità di impostare una distribuzione da zero o lavorare da una distribuzione esistente.
Bryce,

1
Questo è ciò che fa.
Piani cottura

2
@hobs Mi stavo divertendo un DependsOnUnknownMigrationpo 'a simulare la nuova migrazione iniziale. Grazie al tuo commento, ho potuto capire che dovrei aggiornare la depends_ondichiarazione ovunque si riferisca a questa app. Questa è davvero la migliore risposta qui. Grazie! :)
manu

55

Grazie alle risposte di Dominique Guardiola e ai piani cottura, mi ha aiutato a risolvere un problema difficile. Tuttavia, ci sono un paio di problemi con la soluzione, ecco la mia opinione su di essa.

L'uso nonmanage.py reset south è una buona idea se hai app di terze parti che usano il Sud, ad esempio django-cms(praticamente tutto usa il Sud).

reset south eliminerà tutta la cronologia delle migrazioni per tutte le app installate.

Ora considera che esegui l'aggiornamento all'ultima versione di django-cms, conterrà nuove migrazioni come 0009_do_something.py. Sud sarà sicuramente confuso quando si tenta di eseguire quella migrazione senza 0001passare attraverso 0008la cronologia delle migrazioni.

È molto meglio / più sicuro ripristinare selettivamente solo le app che stai mantenendo .


Prima di tutto, assicurati che le tue app non abbiano alcuna desincronizzazione tra migrazioni su disco e migrazioni eseguite sul database. Altrimenti ci sarà mal di testa.

1. Elimina la cronologia delle migrazioni per le mie app

sql> delete from south_migrationhistory where app_name = 'my_app';

2. Elimina le migrazioni per le mie app

$ rm -rf my_app/migrations/

3. Creare nuove migrazioni iniziali per le mie app

$ ./manage.py schemamigration --initial my_app

4. Fake esegue le migrazioni iniziali per le mie app

Ciò inserisce le migrazioni south_migrationhistorysenza toccare le tabelle effettive:

$ ./manage.py migrate --fake my_app

I passaggi 3 e 4 sono in realtà solo una variante più lunga di manage.py convert_to_south my_app, ma preferisco quel controllo extra, in una situazione così delicata come la modifica del database di produzione.


2
Ho modificato la mia risposta per includere correzioni per i problemi che hai riscontrato (solo indovinandoli in base alla tua risposta) e l'ho testato su un database di produzione con milioni di righe.
Piani cottura

2
Questo è praticamente quello che stiamo facendo. Se usi l'opzione --delete-ghost-migrations al passaggio 4, puoi lasciare il passaggio 1.
tochch

È necessario specificare esplicitamente i nomi delle app ./manage.py migrate --fakese non si desidera falsificare la migrazione di altre app in attesa di migrazioni.
wadim,

2
@wadim Quindi passaggio 0: "assicurarsi di non avere alcuna desincronizzazione tra le migrazioni sul disco e le migrazioni eseguite sul database".
giovedì

@thnee Right. Probabilmente vale la pena ricordare che ti riferisci a tutte le app installate nel passaggio 0. Conosci un modo semplice per eseguire il passaggio 0?
wadim,

7

Come thnee (vedi la sua risposta), stiamo usando un approccio più delicato al suggerimento dell'autore del sud (Andrew Godwin) citato altrove qui, e stiamo separando ciò che facciamo con la base di codice da ciò che facciamo nel database, durante la distribuzione , perché abbiamo bisogno che le distribuzioni siano ripetibili:

Cosa facciamo nel codice:

# Remove all the migrations from the app
$ rm -fR appname/migrations
# Make the first migration (don't touch the database)
$ ./manage.py schemamigration appname --initial

Cosa facciamo al database una volta distribuito quel codice

# Fake the migration history, wiping out the rest
$ ./manage.py migrate appname --fake --delete-ghost-migrations

Penso di aver fatto la stessa cosa, ma di eliminare manualmente le voci del database, anziché utilizzare --delete_ghoist-migrations. La tua strada è un po 'più bella.
wobbily_col,

1

Se stai solo lavorando sulla macchina dev, ho scritto un comando di gestione che fa praticamente quello che Dominique ha suggerito.

http://balzerg.blogspot.co.il/2012/09/django-app-reset-with-south.html

A differenza del suggerimento dell'autore del sud, questo NON NOCENDA altre app installate che utilizzano il sud.


E se, a differenza dell'autore, vuoi mantenere le migrazioni esistenti (ovvero vuoi ripristinare l'app e la cronologia delle migrazioni, ma mantenere le migrazioni effettive), puoi provare questo: goo.gl/0ZnWm
mgalgs

1

Di seguito è solo se si desidera ripristinare tutte le app. Si prega di eseguire il backup di tutti i database prima di tale lavoro. Annota anche la tua depend_on nei file iniziali, se ce ne sono.

Per una volta:

(1) find . -type d -name migrations -exec git rm -rf '{}' \;
(2) find . -type d -name migrations -exec rm -rf '{}' \;
(3) ./manage.py schemamigration <APP_NAME> --initial
(4) [GIT COMMIT]

Prova il bootstrap del tuo progetto prima del push. Quindi, per ogni macchina locale / remota, applicare quanto segue:

(5) [GIT PULL]
(6) ./manage.py reset south
(7) ./manage.py migrate --fake

Esegui l'iniziale (3) per ogni app che desideri coinvolgere nuovamente. Notare che, reset (6) eliminerà solo la cronologia delle migrazioni, quindi non dannosa per le librerie. Le migrazioni false (7) riporteranno la cronologia delle migrazioni di tutte le app di terzi installate.


0

elimina il file necessario dalla cartella dell'app

percorso dell'istanza

 cd /usr/local/lib/python2.7/dist-packages/wiki/south_migrations

wiki-è la mia app

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.