2010-01-18 35 views
6

Tengo un script de importación que ejecuta una serie de comandos para transferir cosas de un DB de Postgres a otro, ambos ejecutando la misma base de código de Django. En su mayor parte, utiliza ./manage.py loaddata para copiar, pero algunos objetos requieren un procesamiento adicional y yo uso el método objects.create() de Django en un script personalizado para copiar los datos. Al hacer esto, se especifica la ID, es decir,Creación de objeto Django y Secuencias de Postgres

MyObject.objects.create(id = 2, title = 'foo') 

Una vez realizado el guión, me estoy dando cuenta de que la secuencia de Postgres está mal en las mesas donde hice objects.create(). Es decir, era 50 antes de la importación, y aún 50 después, aunque ahora la tabla tiene 150 objetos. Esto, por supuesto, genera errores al crear nuevos objetos, ya que trata de usar un ID que ya existe (en todas estas tablas, el ID es solo un campo de autoincremento de vainilla). Sin embargo, las tablas que se rellenaron a través de ./manage.py loaddata parecen estar bien.

Soy consciente de que puedo restablecer manualmente estas tablas con el ./manage.py sqlsequenreset de Django, pero tengo curiosidad de por qué la secuencia parece estar fuera de control en primer lugar. Does objects.create() no lo incrementa? ¿Estoy pasando por alto algo obvio?

+0

¿No hay formas mejores de sincronizar la base de datos? ¿Revisaste la estructura de la tabla sobre el incremento automático en el campo de identificación? – Prashanth

+2

No estoy actualizado con material específico de postgres, pero supongo que cada vez que se inserta una fila con un 'nulo' para una columna de identidad, se" completa "mediante postgres (a la auto_increment) y la secuencia se incrementa Si especifica una identificación usted mismo, pasa por alto esta lógica y simplemente inserta la fila directamente. Supongo que django no intenta incrementar el número de secuencia, dejándolo en el motor de la base de datos. – shylent

+0

@shylent También estoy volando intuitivamente aquí, pero parece que el propósito de tener una variable de secuencia incrementada en la base de datos es evitar tener que ejecutar un máximo sobre los identificadores para cada registro en cada inserción cuando no se especifica el ID . Para mantener la secuencia actualizada en el caso de uso del OP, se debe ejecutar un máximo después de cada inserción cuando se especifica el id. Creo que está justificado exigir al usuario que solicite manualmente la actualización. –

Respuesta

12

todo funciona bien. La creación de django() no tiene nada que ver con la incementación de secuencia directamente. brevemente:

  • postgresql auto incrementando (tipo 'serial') es sólo un acceso directo de 'crear secuencia + crear número entero campo con valor de secuencia como predeterminada'
  • de Django AutoField clave primaria (id número entero si no especificado por usted) solo crea un campo en serie
  • cuando especifica el ID manualmente, postgres inserta el valor en la base de datos . cuando especifica un valor, , omite el parámetro 'predeterminado', , que es un comportamiento adecuado.

por lo tanto, si desea que sus inserciones incrementen la secuencia de la manera que prefiera, debe cambiar manualmente el valor de la secuencia utilizando SELECT setval ('sequence_name', int_value); de lo contrario, déjelo nulo y se incrementará automáticamente: seleccione el valor actual e increméntelo +1 (si no se especifica de manera diferente en la definición de secuencia).

Otra idea es crear el objeto y luego actualizar el id (por supuesto, no se puede usar) y al final establecer el valor de secuencia para el id. Máximo.

+0

Gracias, hombre, me salvas – peter

2

El incremento automático campos de trabajos, pero yo debe hacer la consulta como

MyObject.objects.create(title='foo') 

sin el campo id, es Autocalculated con la base de datos.

+0

Supongo que lo que me interesa aquí es que el JSON producido por el propio comando dumpdata de Django especifica los PK de los objetos, y el comando loaddata parece respetar esos PK sin que la secuencia de Postgre se estropee. Entonces, ¿por qué objects.create no lo hace? Tal vez es simplemente un descuido? – KRH

+0

@KRH creo que este código en 'django/core/management/commands/load.py: 188' puede explicarnos esa pregunta. – diegueus9

+0

Entendido. Supongo que estoy algo sorprendido de que objects.create() no haga esto considerando los errores de clave primaria que puede engendrar, pero supongo que desde una perspectiva de diseño ellos consideran que es el problema de los usuarios resolver. – KRH

Cuestiones relacionadas