2012-10-11 33 views
63

Quiero eliminar nula = True desde un campo de texto:sur: no se puede ALTER TABLE, ya que tiene pendiente eventos de activación

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

creé una migración de esquema:

manage.py schemamigration fooapp --auto 

Dado que algunas columnas de pie de página contienen NULL consigo este error si se me acaba la migración:

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

he añadido esto a la migración de esquema:

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

Ahora me sale:

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

Cuál es el problema?

+0

Esta pregunta es similar: http://stackoverflow.com/questions/28429933/django-migrations-using-runpython-to-commit-changes y tenía respuestas que me resultaron más útiles. – SpoonMeiser

Respuesta

73

Cada migración se realiza dentro de una transacción. En PostgreSQL no debe actualizar la tabla y luego alterar el esquema de la tabla en una transacción.

Debe dividir la migración de datos y la migración de esquema. En primer lugar crear la migración de datos con este código:

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

continuación, crear el esquema de la migración:

manage.py schemamigration fooapp --auto 

Ahora tienen dos transacciones y la migración en dos pasos debería funcionar.

+5

Probablemente, PostgreSQL cambió su comportamiento con respecto a tales transacciones, ya que logré ejecutar una migración con cambios de datos y de esquema en mi máquina de desarrollo (PostgreSQL 9.4) mientras fallaba en el servidor (PostgreSQL 9.1). –

11

Acabo de solucionar este problema. También puede usar db.start_transaction() y db.commit_transaction() en la migración de esquema para separar los cambios de datos de los cambios de esquema. Probablemente no esté tan limpio como para tener una migración de datos separada, pero en mi caso necesitaría un esquema, datos y luego otra migración de esquema, así que decidí hacerlo todo de una vez.

+5

El problema con esta solución es esta: ¿Qué ocurre si la migración falla después de db.commit_transaction()? Prefiero usar tres migraciones, si lo necesita: schema-mig, data-mig, schema-mig. – guettli

+0

Ver: http://django.readthedocs.io/en/latest/ref/migration-operations.html En bases de datos que admiten transacciones DDL (SQLite y PostgreSQL), las operaciones RunPython no tienen ninguna transacción agregada automáticamente además las transacciones creadas para cada migración. Por lo tanto, en PostgreSQL, por ejemplo, debe evitar combinar los cambios de esquema y las operaciones RunPython en la misma migración o puede golpear errores como OperationalError: no puede ALTERAR TABLE "mitabla" porque tiene eventos desencadenantes pendientes. –

75

Otra razón para esto puede deberse a que intenta establecer una columna en NOT NULL cuando en realidad ya tiene valores NULL.

+1

¡Esto es enorme! Gracias por esto. –

+2

Para solucionar esto, puede usar una migración de datos o manualmente (shell manage.py) entrar y actualizar los valores no compatibles – mgojohn

+0

@mgojohn ¿Cómo lo hace? – pyramidface

Cuestiones relacionadas