2012-04-03 21 views
8

Uso el sur para migrar mis modelos django. Sin embargo, hay un error desagradable en el sur. No establece valores predeterminados en las bases de datos de Postgres. Ejemplo:django south migration, no establece el valor predeterminado

created_at = models.DateTimeField(default = datetime.now) 
tag_id = models.PositiveIntegerField(default = 0) 

Sur añadirá estos 2 campos a la base de datos, pero no para establecer sus valores predeterminados, que hay que hacer manualmente.

¿Hay algún parche para este error?

ACTUALIZACIÓN ya había intentado fijar fecha predeterminada con auto_now_add=True, pero que tampoco es la configuración de ajustes. Agregar null=True en el campo agrega un db.alter_column en el script de migración producido por el sur. Pero eso solo elimina NOT NULL restricción, no agrega un valor predeterminado. Lo mismo para el campo entero

Respuesta

11

Esto no es un error, en el sur o en otro lugar.

Creo que está confundido acerca de cómo funcionan los valores predeterminados en Django en general. Django no establece valores predeterminados en el esquema de la base de datos. Los aplica directamente en Python, cuando se crea una nueva instancia. Puede verificar esto haciendo manage.py sqlall y ver que el SQL generado no contiene los atributos default.

+2

¿Cómo puedo aplicar un valor predeterminado en la base de datos de Postgres? Tengo apis que negocian directamente con la base de datos creada por django. Esperan que los valores predeterminados estén en su lugar. – jerrymouse

+5

Tendrá que usar SQL personalizado para modificar el esquema usted mismo. Puede hacer esto dentro de South pasando el SQL a ['db.execute'] (http://south.aeracode.org/docs/databaseapi.html#db-execute). –

+3

Daniel simplemente porque Django intenta evitar que los usuarios modifiquen los valores predeterminados de campo en el nivel de esquema, eso no significa que NO DEBEN ser capaces de hacerlo. He publicado una solución real a continuación. – galarant

21

Si está auto-generar sus migraciones usando:

./manage.py schemamigration app_name --auto 

Luego hay que hacer una pequeña edición en la migración antes de que realmente lo aplica. Id a la migración generada (debería llamarse algo así como nombre_apl/migraciones/000X__auto_add_field_foo.py) y busque el argumento:

keep_default=False 

en la llamada db.add_column. Basta con cambiar esto:

keep_default=True 

y Django se aplicará ahora a su valor por defecto en el esquema actual, además de las filas existentes. Sería genial si South tuviera algún tipo de configuración para generar este parámetro como True de forma predeterminada, pero no tuvo tanta suerte. Tendrá que hacer esta edición cada vez.

+0

+1 Mucho más fácil que escribir SQL personalizado –

+5

+1. Desafortunadamente ['keep_default' está en desuso en South 0.8.1] (http://south.readthedocs.org/en/latest/releasenotes/0.8.1.html#keep-default-fully-deprecated) – Pankrat

+0

maldición, Pankrat tiene razón ... – galarant

2

Como se mencionó en las respuestas anteriores, el mecanismo predeterminado en django se implementa en la clase de modelo, y no es relevante para las migraciones al sur.

Además, desde el sur 0,8, the keep_default flag is deprecated, y no agregará el valor predeterminado a su modelo.

Lo que hago para resolver esto es escribir una migración personalizada para agregar el valor predeterminado. Puede hacerlo mediante la creación de una por separado data migration:

./manage.py datamigration your_app_name migration_name 

y añadir la siguiente línea a la función forwards:

orm.YourModel.objects.update(field_name = DEFAULT_VALUE) 

Como alternativa, en lugar de crear una nueva migración, puede modificar la migración originales:

  1. agregue no_dry_run = True a la clase misma (para que tenga acceso al ORM).
  2. agregue orm.YourModel.objects.update(field_name = DEFAULT_VALUE) al final de la función forwards.

De esta manera no tiene que escribir una migración hacia atrás, porque ya tiene la columna de borrar original.

Cuestiones relacionadas