Why can't I save my model instances after editing them?
I have a model which I can instantiate just fine, but once created, if I attempt to save it I get an IntegrityError saying that the primary key must be unique. What's causing this?
There are other models that inherit from Node, and they're giving me the same problem.
Here's my model:
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()
Here's the SQL it generates:
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
)
;
And what happens when I attempt to save a preexisting model instance:
>>> 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
Here are the queries that this runs:
>>> for q in connection.queries:
... print q['sql'] + "\n\n"
...
SELECT MAX("main_node"."tree_id") AS "tree_id__max" FROM "main_node"
INSE开发者_开发百科RT 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)
Why is it trying to insert into main_book when I'm resaving the already created instance?
Are you over-riding the "save()" method in any of your models? I had a similar issue and after a lot of digging, found out it was because of a small mistake in my over-ridden "save()".
Can you please post the whole of your model definitions? (from the generated SQL, it looks like what you have posted is not complete)
I can't answer why your situation isn't working but I can suggest a workaround.
I'm not familiar with MPTT, but does this work or does it cause the same problem?
b = Book(title='C+ for Dummies', isbn13='111-1111111111')
b.save()
b.title = "C++ for Dummies"
b.save()
You must have some unique constraints on the database that you're not aware of OR your database table's auto-increment counter has been reset to some value that is not valid.
This link seems to be of value: http://old.nabble.com/Reset-auto-increment---truncate-td16494119.html
Think about it like this, the auto-increment counter is picking values for your primary key that already exist because the counter's value is set lower than that of the last entry in the table and so when it picks the next value, it picks a value that already exists.
Update: Something weird is going on. From the SQL queries in your question, it appears its attempting to INSERT again. Try:
b.save(force_update=True)
This particular scenario does not seem to warrant a force_update=True
, but maybe its a bug in MPTT or Django code.
Try to compare the following objects and see if you can find any differences:
b = Book(title='C+ for Dummies', isbn13='111-1111111111')
and
b = Book.objects.create(title='c+ for dummies', isbn13='111-1111111111', description='nt')
精彩评论