Почему я не могу сохранить экземпляры моделей после их редактирования?
У меня есть модель, которую я могу создать просто отлично, но после ее создания, если я пытаюсь сохранить ее, я получаю IntegrityError, в которой говорится, что первичный ключ должен быть уникальным. Что вызывает это?
Есть другие модели, которые наследуются от Node, и они создают мне ту же проблему.
Вот моя модель:
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()
Вот SQL, который он генерирует:
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
)
;
И что происходит, когда я пытаюсь сохранить существующий экземпляр модели:
>>> 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
Вот запросы, которые это выполняет:
>>> 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)
Почему он пытается вставить в main_book, когда я сохраняю уже созданный экземпляр?
4 ответа
Вы используете метод save() в любой из ваших моделей? У меня была похожая проблема, и после долгих поисков я обнаружил, что это из-за маленькой ошибки в моем переопределенном "save()".
Не могли бы вы опубликовать все определения вашей модели? (из сгенерированного SQL похоже, что то, что вы опубликовали, не завершено)
Я не могу ответить, почему ваша ситуация не работает, но я могу предложить обходной путь.
Я не знаком с MPTT, но это работает или это вызывает ту же проблему?
b = Book(title='C+ for Dummies', isbn13='111-1111111111')
b.save()
b.title = "C++ for Dummies"
b.save()
Попробуйте сравнить следующие объекты и посмотреть, сможете ли вы найти какие-либо различия:
b = Book(title='C+ for Dummies', isbn13='111-1111111111')
а также
b = Book.objects.create(title='c+ for dummies', isbn13='111-1111111111', description='nt')
У вас должны быть некоторые уникальные ограничения для базы данных, о которых вы не знаете, ИЛИ счетчик автоинкремента таблицы базы данных был сброшен до некоторого недопустимого значения.
Эта ссылка имеет ценность: http://old.nabble.com/Reset-auto-increment---truncate-td16494119.html
Подумайте об этом следующим образом: счетчик автоинкремента выбирает значения для вашего первичного ключа, которые уже существуют, потому что значение счетчика установлено ниже, чем значение последней записи в таблице, и поэтому, когда он выбирает следующее значение, он выбирает значение это уже существует.
Обновление: происходит что-то странное. Судя по SQL-запросам в вашем вопросе, он снова пытается ВСТАВИТЬ. Пытаться:
b.save(force_update=True)
Этот конкретный сценарий, кажется, не гарантирует force_update=True
, но, возможно, это ошибка в коде MPTT или Django.