2011-06-01 8 views
6

Tengo un modelo que puedo instanciar muy bien, pero una vez creado, si intento guardarlo obtengo un IntegrityError que dice que la clave primaria debe ser única. ¿Qué está causando esto?¿Por qué no puedo guardar las instancias de mi modelo después de editarlas?

Hay otros modelos que heredan de Node y me están dando el mismo problema.

Aquí es mi modelo:

class Node(MPTTModel): 
    title = models.CharField(max_length=255) 
    parent = models.ForeignKey('self', null=True, blank=True, 
           related_name='children') 

class Book(Node): 
    isbn13 = models.CharField(max_length=14) 
    description = models.TextField() 

Aquí está el SQL que genera:

CREATE TABLE "main_node" (
    "id" integer NOT NULL PRIMARY KEY, 
    "title" varchar(255) NOT NULL, 
    "parent_id" integer, 
    "type" varchar(1) NOT NULL, 
    "lft" integer unsigned NOT NULL, 
    "rght" integer unsigned NOT NULL, 
    "tree_id" integer unsigned NOT NULL, 
    "level" integer unsigned NOT NULL 
) 
; 
CREATE TABLE "main_book" (
    "node_ptr_id" integer NOT NULL PRIMARY KEY REFERENCES "main_node" ("id"), 
    "isbn13" varchar(14) NOT NULL, 
    "description" text NOT NULL 
) 
; 

Y lo que sucede cuando intento guardar una preexistente instancia de modelo:

>>> b = Book.objects.create(title='c+ for dummies', isbn13='111-1111111111', description='nt') 
>>> b.title='c++ for dummies' 
>>> b.save() 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "C:\Users\Jackie\Desktop\Code\ProjectName\main\models.py", line 56, in save 
    super(Book, self).save(self, *args) 
    File "C:\Python27\lib\site-packages\django\db\models\base.py", line 460, in save 
    self.save_base(using=using, force_insert=force_insert, force_update=force_update) 
    File "C:\Python27\lib\site-packages\django\db\models\base.py", line 553, in save_base 
    result = manager._insert(values, return_id=update_pk, using=using) 
    File "C:\Python27\lib\site-packages\django\db\models\manager.py", line 195, in _insert 
    return insert_query(self.model, values, **kwargs) 
    File "C:\Python27\lib\site-packages\django\db\models\query.py", line 1436, in insert_query 
    return query.get_compiler(using=using).execute_sql(return_id) 
    File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py", line 791, in execute_sql 
    cursor = super(SQLInsertCompiler, self).execute_sql(None) 
    File "C:\Python27\lib\site-packages\django\db\models\sql\compiler.py", line 735, in execute_sql 
    cursor.execute(sql, params) 
    File "C:\Python27\lib\site-packages\django\db\backends\util.py", line 34, in execute 
    return self.cursor.execute(sql, params) 
    File "C:\Python27\lib\site-packages\django\db\backends\sqlite3\base.py", line 234, in execute 
    return Database.Cursor.execute(self, query, params) 
IntegrityError: PRIMARY KEY must be unique 

Aquí están las consultas que esto ejecuta:

>>> for q in connection.queries: 
... print q['sql'] + "\n\n" 
... 
SELECT MAX("main_node"."tree_id") AS "tree_id__max" FROM "main_node" 


INSERT INTO "main_node" ("title", "parent_id", "type", "lft", "rght", "tree_id", "level") VALUES (c+ 
for dummies, None, B, 1, 2, 1, 0) 


INSERT INTO "main_book" ("node_ptr_id", "isbn13", "description") VALUES (1, 111-1111111111, nt) 




SELECT (1) AS "a" FROM "main_node" WHERE "main_node"."id" = 1 LIMIT 1 


UPDATE "main_node" SET "title" = c++ for dummies, "parent_id" = NULL, "type" = B, "lft" = 1, "rght" 
= 2, "tree_id" = 1, "level" = 0 WHERE "main_node"."id" = 1 


INSERT INTO "main_book" ("node_ptr_id", "isbn13", "description") VALUES (1, 111-1111111111, nt) 

¿Por qué está intentando insertar en main_book cuando estoy volviendo a guardar la instancia ya creada?

Respuesta

1

Debe tener algunas limitaciones exclusivas en la base de datos de las que no tenga conocimiento O el contador de incremento automático de la tabla de su base de datos se haya restablecido en algún valor que no sea válido.

Este vínculo parece ser de valor: http://old.nabble.com/Reset-auto-increment---truncate-td16494119.html

Piense en ello como esto, el contador aún se está recuperando los valores de la clave principal que ya existen porque el valor del contador se ajusta más baja que la de la última entrada en la tabla y, por lo tanto, cuando elige el siguiente valor, elige un valor que ya existe.

Actualización: Algo raro está ocurriendo. De las consultas SQL en su pregunta, parece que intenta INSERTAR de nuevo. Proveedores:

b.save(force_update=True) 

Este escenario particular no no parecen justificar una force_update=True, pero tal vez es un error en MPTT o Django código.

+0

Mi base de datos se ha creado recientemente a través de syncdb. Las únicas limitaciones son las que hay en mi modelo y las heredadas de MPTTModel. Books.object.create funciona bien, así que realmente no tienen idea de por qué estoy recibiendo este error. Guardar la instancia del modelo de nuevo solo debe actualizar la columna (en realidad dos, debido a la forma en que funciona la herencia del modelo). – Jackie

2

No puedo responder por qué su situación no funciona, pero puedo sugerir una solución.

No estoy familiarizado con MPTT, pero ¿funciona o causa el mismo problema?

b = Book(title='C+ for Dummies', isbn13='111-1111111111') 
b.save() 
b.title = "C++ for Dummies" 
b.save() 
1

tratar de comparar los siguientes objetos y ver si se puede encontrar ninguna diferencia:

b = Book(title='C+ for Dummies', isbn13='111-1111111111') 

y

b = Book.objects.create(title='c+ for dummies', isbn13='111-1111111111', description='nt') 
4

¿Tiene más de montar el "save()" método en el cualquiera de tus modelos? Tuve un problema similar y después de una gran cantidad de excavaciones, descubrí que se debía a un pequeño error en mi "guardar()" superpuesto.

¿Puede publicar la totalidad de las definiciones de su modelo?(del SQL generado, parece que lo que ha publicado no está completo)

+0

¿Qué error? –

+1

Había cometido el error de pasar el argumento "self" a la llamada al método super.save() dentro del "guardado()" over-ridden , es decir, había hecho algo similar a: 'super (Tag, auto) .save (auto, * args, ** kwargs) // Esto está mal ' mientras que yo tenía que hacer:' super (etiqueta, auto) .save (* args, ** kwargs) ' sí , error estúpido, ¡pero me hizo tropezar durante horas! –

Cuestiones relacionadas