python - 为什么Django查询要检查唯一性?

标签 python django postgresql django-models django-database

tl;dr:为什么 Django 对 INSERT 的唯一性检查需要 SELECT 查询,我可以永久禁用它吗?

我正在努力高度优化正在写入 PSQL 数据库的 Django 应用程序。我有一个 uuid 列,它是我模型的一部分的 primary_key。它是模型中唯一的 unique 字段。

id = models.UUIDField(
    primary_key = True,
    default = uuid.uuid4,
    editable = False,
    null = False,
    blank = False,
    help_text = 'The unique identifier of the Node.'
)

我遇到的问题是,当尝试保存 新项目时,Django 在插入 之前自动执行唯一性检查查询:

SELECT (1) AS "a" FROM "customer" WHERE "customer"."id" = \'1271a1c8-5f6d-4961-b2e9-5e93e450fd4e\'::uuid  LIMIT 1

这会导致额外的数据库往返。我知道该字段必须是唯一的,但当然 Django 已经在数据库级别配置了它 - 所以如果它试图插入具有非唯一字段的行它会得到一个错误。

我已经实现了一个解决方法,通过将以下内容添加到我的 model 来抑制查询:

def validate_unique(self, *args, **kwargs):

    # Make sure that we never validate if ID is unique. Duplicates OK.
    current_exclude = set(kwargs.get('exclude', []))
    current_exclude.add('id')
    kwargs['exclude'] = list(current_exclude)

    super().validate_unique(*args, **kwargs)

这将确保 id 字段的唯一性从不被检查。

这有效,我没有得到额外的查询。我还验证了如果我确实尝试重新插入一个重复的 UUID,我确实会收到一个错误,将数据库作为源。

我的问题是:Django 为什么要这样做?我很想阻止 Django 永远 检查唯一性,除非到数据库的额外往返完成一些有值(value)的目的。

环境:

django==2.2.12
psycopg2-binary==2.8.5

最佳答案

在 Django 中,模型验证模型保存截然不同。看来无论您在做什么都会触发验证。

将这些作为单独的步骤有很多充分的理由。一是与数据库约束相比,您可以在任意 Python 代码中表达更多的约束。另一个是它允许您生成比尝试解析非标准化数据库错误所获得的描述性更多的错误消息。另一个是,有时您只是想知道某些内容是否有效,但不想实际保存它。

默认情况下,Django does not validate models在拯救他们之前。不过,一些 Django 组件,如管理(更一般地说,ModelForms)会触发验证。

因此,您需要弄清楚为什么在您的情况下会触发验证,如果这不是您想要的,请阻止它。

关于python - 为什么Django查询要检查唯一性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63742640/

相关文章:

postgresql - Slick 与 PostgreSQL Scala SBT Intellij IDEA

Python广度优先搜索矩阵打印路径

python - Django model.foreignKey 并返回 self.text 错误

python - 在 Django 中过滤超过 0000-00-00 日期的对象

django - 由于 “grep -v”带有尾随\r,因此在构建Django应用程序时,Docker编写失败

ruby-on-rails - 奇怪的字符编码问题

sql - 如何在 libpq 中使用 PQexecParams?

python - 在数据库创建时提供枚举

python - 在路径中包含 Python 库?

python - Django 管理员保存错误 : get_db_prep_value() got an unexpected keyword argument 'connection'