umana - Django 1.8: creare migrazioni iniziali per lo schema esistente




migrazioni nella storia wikipedia (4)

Finalmente ha funzionato, anche se non so perché e spero che funzionerà in futuro.
Dopo aver fatto numerose prove e aver visitato il sito di sviluppo di Django ( link ).
Ecco i passaggi (per chi incontra questo problema):

  1. Svuota la tabella django_migrations : delete from django_migrations;
  2. Per ogni app, elimina la cartella delle migrations : rm -rf <app>/migrations/
  3. Reimposta le migrazioni per le app "integrate": python manage.py migrate --fake
  4. Per ogni esecuzione di app: python manage.py makemigrations <app> . Prenditi cura delle dipendenze (i modelli con ForeignKey dovrebbero funzionare secondo il loro modello genitore).
  5. Infine: python manage.py migrate --fake-initial

Dopo di che ho eseguito l'ultimo comando senza il --fake-initial , solo per essere sicuro.

Ora tutto funziona e posso usare normalmente il sistema delle migrazioni.

Sono sicuro di non essere l'unico a riscontrare questo problema. Deve essere documentato meglio e persino semplificato.

Aggiornamento per gli utenti di Django 1.9:
Ho avuto di nuovo questo scenario con un Django 1.9.4 e il passaggio 5 non è riuscito.
Tutto quello che dovevo fare è sostituire --fake-initial con --fake per farlo funzionare.

Ho avviato un progetto django 1.8, che utilizza il sistema delle migrazioni.
In qualche modo lungo la strada le cose sono diventate disordinate, quindi ho cancellato le cartelle e la tabella delle migrazioni dal DB, e ora sto cercando di ricostruirle, senza successo.

Ho tre app (3 file models.py ) e i modelli riflettono ESATTAMENTE le tabelle!

L'approccio migliore che ho trovato finora è stato:

  1. Cancella tutte le cartelle delle migrations . Fatto!
  2. Elimina tutto dalla tabella django_migrations . Fatto!
  3. Esegui python manage.py makemigrations --empty <app> per ogni app. Fatto!
  4. Esegui python manage.py migrate --fake . Fatto! (anche se funziona solo se lo makemigrations dopo ogni comando di makemigrations .

Ora aggiungo un nuovo campo, makemigrations comando makemigrations e ricevo il seguente errore:
django.db.utils.OperationalError: (1054, "Unknown column 'accounts_plan.max_item_size' in 'field list'")

Ho bruciato ORE su questa cosa. In che modo posso inizializzare le migrazioni in modo da poter continuare a lavorare senza interruzioni della migrazione ogni volta?

Perché è così complicato? Perché non esiste un semplice one-liner: initiate_migrations_from_schema ?

MODIFICARE:
Ora le cose diventano ancora più cattive. Ho troncato la tabella django_migrations ed eliminato tutta la cartella delle migrations .
Ora provo a eseguire python manage.py migrate --fake-initial (qualcosa che ho trovato nei documenti DEV), solo per configurare tutte le app "interne" di Django (autenticazione, sessione, ecc.) E sto ottenendo:
(1054, "Unknown column 'name' in 'django_content_type'") .
Ora, questa "colonna" non è una colonna reale. È una proprietà @property definita nell'app di contenttypes di Django. COSA STA SUCCEDENDO QUI? Perché identifica la proprietà name come una colonna reale?


Grazie - Ho lavorato su questo problema per un po 'e la tua lista delle migliori pratiche è stata davvero utile. Questo potrebbe potenzialmente aiutare i neofiti a python come me:

Se stai iniziando con un set di modelli esistente, cancella tutte le migrazioni precedenti che hai effettuato!

La mia situazione era che ho iniziato con sqlite solo per capire django e poi sono passato a un mysql db - e ha continuato a generare un errore 1053, probabilmente cercando di applicare una migrazione precedente non aveva le risorse per risolvere ...


Se si utilizzano router, potrebbe esserci un problema. Controlla il metodo allow_migrate se viene eseguito correttamente in routers.py . Prova a impostare il valore di ritorno sempre su True e controlla se risolve il problema,

def allow_migrate(self, db, app_label, model_name=None, **hints):
    return True

django ..., 1.8, 1.9, ...

Quello che vuoi ottenere è schiacciare le migrazioni esistenti e utilizzarle per sostituirle.

Come farlo bene senza usare alcun comando al rilascio (un caso senza impatto sul database e sui colleghi).

  1. Per ogni app, elimina la cartella delle migrazioni: mv <app>/migrations/ <app>/migrationsOLD/

  2. Per ognuna di quelle app eseguite: python manage.py makemigrations <app> .

  3. Personalizza ogni nuova migrazione:

    • se disponi di un'app complessa o di più app e modelli correlati tra loro, per evitare CircularDependencyError o ValueError: Unhandled pending operations for models :

      preparare la seconda migrazione vuota in <app> 0002_initial2.py (inserire la dipendenza da app_other::0001_initial.py e <app> :: 0001_initial.py - tutti gli ForeignKey, M2M relativi ai modelli creati nel passaggio di migrazione 0001 in altre app)

      Tutto deve essere in ordine - a volte occorreranno più migrazioni per prepararsi. Prenditi cura dell'attributo delle dependencies qui in ogni migrazione.

    • prenditi cura dei valori iniziali: verifica te stesso tutte RunPython azioni RunPython da migrationsOLD e, se necessario, copia il codice nella nuova migrazione iniziale.

    • (facoltativo per --fake-initial ) Aggiungi initial=True a tutte le nuove classi di migrazione (anche 0002 se è stato aggiunto).

    • Aggiungi replaces attributo nella nuova classe di migrazione. (come la propria abitudine a squashmigrations ). Inserisci lì tutte le vecchie migrazioni da <app>
  4. Verifica tutto con makemigrations .

    asserire "Nessuna modifica rilevata"

  5. Controlla se migrate -l mostra [x] ovunque

    asserire simili:

    [X] 0001_initial

    [X] 0002_initial2 (102 migrazioni schiacciate)

Esempio:

Per i vecchi:

0001_initial.py
0002_auto.py
...
0103_auto.py

preparare:

0001_initial.py
0002_initial2.py  (optional but sometimes required to satisfy dependency)

e aggiungi a replaces l'ultimo (0002 qui, può essere 0001):

replaces = [(b'<app>', '0002_auto.py'), ..., (b'<app>', '0103_auto.py')]

0001_initial.py dovrebbe essere chiamato allo stesso modo di quello vecchio.

0002_initial2.py è nuovo, ma è un sostituto delle migrazioni precedenti, quindi Django lo tratterà come caricato.





django-migrations