2012-10-11 15 views
63

Voglio rimuovere nulla = True da un TextField attesa:sud: non può ALTER TABLE perché ha eventi di trigger

- footer=models.TextField(null=True, blank=True) 
+ footer=models.TextField(blank=True, default='') 

Ho creato una migrazione dello schema:

manage.py schemamigration fooapp --auto 

Poiché alcune colonne piè di pagina contengono NULL ottengo questo errore se corro la migrazione:

django.db.utils.IntegrityError: column "footer" contains null values 

ho aggiunto questo per la migrazione dello schema:

for sender in orm['fooapp.EmailSender'].objects.filter(footer=None): 
     sender.footer='' 
     sender.save() 

Ora ho:

django.db.utils.DatabaseError: cannot ALTER TABLE "fooapp_emailsender" because it has pending trigger events 

Cosa c'è di sbagliato?

+0

Questa domanda è simile: http://stackoverflow.com/questions/28429933/django-migrations-using-runpython-to-commit-changes e ha avuto risposte che mi sono state più utili. – SpoonMeiser

risposta

73

Ogni migrazione è all'interno di una transazione. In PostgreSQL non è necessario aggiornare la tabella e quindi modificare lo schema della tabella in un'unica transazione.

È necessario dividere la migrazione dei dati e la migrazione dello schema. In primo luogo creare la migrazione dei dati con questo codice:

for sender in orm['fooapp.EmailSender'].objects.filter(footer=None): 
    sender.footer='' 
    sender.save() 

quindi creare la migrazione dello schema:

manage.py schemamigration fooapp --auto 

Ora avete due transazioni e la migrazione in due fasi dovrebbe funzionare.

+5

PostgreSQL probabilmente ha cambiato il suo comportamento in merito a tali transazioni, poiché sono riuscito a eseguire una migrazione con modifiche di dati e di schema sulla mia macchina di sviluppo (PostgreSQL 9.4) mentre non funzionava sul server (PostgreSQL 9.1). –

11

Hanno appena colpito questo problema. È inoltre possibile utilizzare db.start_transaction() e db.commit_transaction() nella migrazione dello schema per separare le modifiche ai dati dalle modifiche dello schema. Probabilmente non è così pulito da avere una migrazione separata dei dati, ma nel mio caso avrei bisogno di schemi, dati e quindi un'altra migrazione dello schema, così ho deciso di farlo tutto in una volta.

+5

Il problema con questa soluzione è questo: cosa succede se la migrazione non riesce dopo db.commit_transaction()? Preferisco utilizzare tre migrazioni, se necessario: schema-mig, data-mig, schema-mig. – guettli

+0

See: http://django.readthedocs.io/en/latest/ref/migration-operations.html Su basi di dati che supportano le operazioni DDL (SQLite e PostgreSQL), le operazioni di RunPython non hanno alcuna transazione aggiunti automaticamente oltre le transazioni create per ogni migrazione. Pertanto, su PostgreSQL, ad esempio, dovresti evitare di combinare le modifiche dello schema e le operazioni di RunPython nella stessa migrazione o potresti ricevere errori come OperationalError: non puoi ALTER TABLE "mytable" perché ha eventi trigger in sospeso. –

75

Un altro motivo potrebbe essere dovuto al fatto che si tenta di impostare una colonna su NOT NULL quando ha già valori NULL.

+1

Questo è enorme! Grazie per questo. –

+2

Per risolvere questo problema è possibile utilizzare una migrazione dei dati o manualmente (shell gestisci.py) entrare e aggiornare i valori non conformi – mgojohn

+0

@mgojohn Come si fa? – pyramidface

Problemi correlati