6

問題なくインスタンス化できるモデルがありますが、一度作成すると、それを保存しようとすると、主キーが一意でなければならないという 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

4 に答える 4

4

モデルのいずれかで「save()」メソッドをオーバーライドしていますか? 私は同様の問題を抱えていましたが、何度も掘り下げた後、上書きされた「save()」の小さな間違いが原因であることがわかりました。

モデル定義全体を投稿していただけますか? (生成されたSQLから、あなたが投稿したものは完全ではないようです)

于 2011-07-28T15:17:30.573 に答える
2

状況が機能しない理由についてはお答えできませんが、回避策を提案することはできます。

私は MPTT に詳しくありませんが、これは機能しますか、それとも同じ問題を引き起こしますか?

b = Book(title='C+ for Dummies', isbn13='111-1111111111')
b.save()
b.title = "C++ for Dummies"
b.save()
于 2011-06-01T15:05:43.500 に答える
1

次のオブジェクトを比較して、違いがあるかどうかを確認してください。

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

b = Book.objects.create(title='c+ for dummies', isbn13='111-1111111111', description='nt')
于 2011-06-17T00:04:05.810 に答える
1

データベースには、認識していない一意の制約がいくつかある必要があります。または、データベース テーブルの自動インクリメント カウンターが無効な値にリセットされています。

このリンクは価値があるようです: http://old.nabble.com/Reset-auto-increment---truncate-td16494119.html

このように考えてみてください。カウンターの値がテーブルの最後のエントリの値よりも低く設定されているため、自動インクリメントカウンターは既に存在する主キーの値を選択しているため、次の値を選択するときに値を選択しますそれはすでに存在します。

更新:何か奇妙なことが起こっています。質問の SQL クエリから、再度 INSERT を試みているようです。試す:

b.save(force_update=True)

この特定のシナリオは保証されないようですがforce_update=True、MPTT または Django コードのバグである可能性があります。

于 2011-06-01T13:37:42.010 に答える