2011-01-06 23 views
5

He estado usando custom primary keys para un modelo en Django. (Esto era porque estaba importando valores en la base de datos y que ya se habían unido de identificación, y que tenía sentido para preservar los valores existentes.)Django: haciendo un auto-incremento PK personalizado?

class Transaction(models.Model): 
    id = models.IntegerField(primary_key=True) 
    transaction_type = models.IntegerField(choices=TRANSACTION_TYPES) 
    date_added = models.DateTimeField(auto_now_add=True) 

Sin embargo, ahora quiero añadir nuevas instancias del modelo a la base de datos, y me gustaría generar automáticamente una clave principal única. Pero si no se especifica la ID en el momento de la creación de la instancia, me sale un error:

t = Transaction(transaction_type=0) 
t.save() 

da:

IntegrityError at /page 
(1048, "Column 'id' cannot be null") 

¿Cómo puedo autogenerar un identificador único para especificar nuevos valores , sin tener que alterar la forma en que importo los valores existentes?

ACTUALIZACIÓN

He escrito este método personalizado, que parece funcionar ...

class Transaction(models.Model): 
    def save(self, *args, **kwargs): 
     if not self.id: 
      i = Transaction.objects.all().order_by('-id')[0] 
      self.id = i.id+1 
     super(Transaction, self).save(*args, **kwargs) 
+0

Tengo curiosidad: ¿cuál fue el problema de tener a django manejando la clave principal si está realizando una importación masiva? Nunca tuve la situación en la que la clave principal era el problema, a menos que esté importando en un sistema de producción/ejecución. –

Respuesta

1

¿Cómo estás importando los valores existentes? Sería trivial escribir algo en su Transaction s __init__ para generar una nueva identificación para usted, pero sin saber cómo está importando los otros valores, no puedo decir con certeza si alterará la forma en que trabaja con ellos.

+0

No estoy seguro de si esto responde a su pregunta, pero: desde un archivo CSV, utilizando un script de importación personalizado, y estableciendo el campo ID de transacción en el ID en el archivo CSV. (También: los importo usando objetos de Django en lugar de SQL directo.) ¿Eso ayuda? – AP257

+0

Sí. En lugar de escribir su 'Transaction's' __init__', anule 'save()' para que primero compruebe si tiene una ID, y luego si no genera una nueva para usted (y luego las llamadas se guardan como siempre)) – girasquid

+0

He intentado anular 'save()' y agregado como una actualización anterior. ¿Podrías decirme si esto parece vagamente sensato y luego aceptaré tu respuesta? ¡Gracias! – AP257

2

Puede usar AutoField para la columna id en lugar de IntegerField. A continuación se debe trabajar para usted:

id = models.AutoField(primary_key=True) 

id ahora aumentará automáticamente y no tendrá problemas de concurrencia, ya que puede encontrar en save método.

2

he terminado usando pieza muy similar de código, pero han hecho un poco más genérica:

def save(self, *args, **kwargs): 
    if self.id is None: 
     self.id = self.__class__.objects.all().order_by("-id")[0].id + 1 
    super(self.__class__, self).save(*args, **kwargs) 

utiliza self.__class__ por lo que sólo se puede copiar y pegar este código a cualquier clase de modelo sin cambiar nada.

0

Si se quita el campo id declarado, Django asumirá automáticamente la siguiente:

id = models.AutoField(primary_key=True) 

En Django 1.8, inspectdb detectará automáticamente auto_increment y utilizar un AutoField al generar modelos.

Cuestiones relacionadas