【发布时间】:2021-04-27 04:26:38
【问题描述】:
今天,我第一次在尝试通过 Django 管理员向我的 postgres 数据库插入新条目时遇到“ON CONFLICT”错误:
ignored_wrapper_args
(False,
{'connection': <django.db.backends.postgresql.base.DatabaseWrapper object at 0x7f0bb08e3d90>,
'cursor': <django.db.backends.postgresql.base.CursorDebugWrapper object at 0x7f0bb094ab50>})
params
(3351, 48, 3351, 212, 3351, 31)
self
<django.db.backends.postgresql.base.CursorDebugWrapper object at 0x7f0bb094ab50>
sql
('INSERT INTO "ktab_entry_tags" ("entry_id", "tag_id") VALUES (%s, %s), (%s, '
'%s), (%s, %s) ON CONFLICT DO NOTHING')
3351 是 自动分配给条目的 ID(如果条目被接受)。 48、212 和 31 是我要在此条目上放置的 3 个标签的 ID。
我已经使用这个我创建的博客应用程序将近 3 年了。我不仅以前从未遇到过这个错误,而且对我来说没有意义。每个条目都有一个唯一的 id。因此,很难想象由于 entry_id、tag_id 和 entry_tag_id 的组合重复而发生冲突的情况。因此,任何此类约束都是多余且不必要的。
但看起来我确实拥有它:
ktab.public.ktab_entry_tags.ktab_entry_tags_entry_id_tag_id_0900d285_uniq(entry_id, tag_id)
和
ktab.public.ktab_entry_tags.ktab_entry_tags_entry_id_tag_id_0900d285_uniq(entry_id, tag_id) UNIQUE
如果第二个是唯一的,为什么两个都以'_uniq'结尾?
我也有两个:
ktab.public.ktab_entry_tags.ktab_entry_tags_pkey(id)
和
ktab.public.ktab_entry_tags.ktab_entry_tags_pkey(id) UNIQUE
请注意,这是 Django 为我创建的中间表,因为它是多对多字段。我开始每人删除一个,但我没有,因为我仍然不明白这是如何导致或解决我的问题 - 或者为什么它现在才出现。
根据 PyCharm / DataGrip,最后一个成功的条目的 id 为 3350。因此,我可以看到与 tag_ids=212、48 和 31 的 entry_id=3351 的新条目没有冲突。我有数据库工具和 SQL 插件。
过滤: tag_id = '48' AND tag_id = '212' AND tag_id = '31' 什么都没有,包括没有错误!
entry_id = '3351' 一样的
entry_id = '3350' 正如预期的那样,得到 3 个结果。 3 个标签各有一个,每个标签都有自己的 ktab_entry_tags id,但都具有相同的 entry_id:
3102,3350,86
3101,3350,13
3100,3350,8
我不太了解“ignored_wrapper_args”,请参阅https://github.com/django/django/blob/main/django/db/backends/utils.py。我猜这是 False 因为它确实有联系?
我看到了这个:Postgres: INSERT if does not exist already 但这不是并发操作。我正在尝试通过 Django 管理员添加一个条目。
但是,我在回溯中也看到了 bulk_create,这对于单个插入没有意义,尤其是 "ignore_conflicts=ignore_conflicts":
/home/malikarumi/.virtualenvs/chronic_all/lib/python3.9/site-packages/django/db/models/query.py, line 506, in bulk_create
...
if objs_without_pk:
fields = [f for f in fields if not isinstance(f, AutoField)]
returned_columns = self._batched_insert( …
objs_without_pk, fields, batch_size, ignore_conflicts=ignore_conflicts,
)
if connection.features.can_return_rows_from_bulk_insert and not ignore_conflicts:
assert len(returned_columns) == len(objs_without_pk)
for obj_without_pk, results in zip(objs_without_pk, returned_columns):
for result, field in zip(results, opts.db_returning_fields):
这个错误可能是因为该条目还没有 ID?我也认为这没有道理。
感谢您的帮助。
ps
在最后一秒我决定检查版本,得到了这个:
PostgreSQL 9.4.26 on x86_64-pc-linux-gnu (Ubuntu 9.4.26-2.pgdg18.04+1), compiled by gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0, 64-bit
看到我的 Postgres 多大了,我有点害怕。我实际上安装了较新的版本,但正如我所说,我已经使用这个应用程序三年了,没有任何问题。在等待您的回答时,我将看到有关升级和删除旧版本的信息。但我也读到“ON CONFLICT”是从 9.5 开始的,那我们该如何解释呢?
Python 3.9.4 Django 3.1.7 Ubuntu 20.04.2 LTS
【问题讨论】:
标签: python django postgresql