【问题标题】:Django upgrade filter/prefetch_related behaviour change?Django 升级过滤器/prefetch_related 行为改变?
【发布时间】:2019-03-03 16:50:57
【问题描述】:

我正在从 Django 1.8.19 升级到 1.11.15,我发现有一段代码出现问题。

特别是这个查询正在做一些与以前不同的事情。

project_groups = brand.project_groups.prefetch_related(
   'project', 'project__score', 'project__themes').filter(
   project=projects
).distinct()

以前(在 Django 1.8 中),根据“project_groups.query”的输出,它产生的 SQL 包括:

... projectgroup.project_id IN [projects query]

现在它会产生 SQL 读取:

... projectgroup.project_id = [projects query]

当 [projects query] 返回不止一行时,这会中断。所以我得到一个:

ProgrammingError: more than one row returned by a subquery used as an expression

我对此次升级代码所做的唯一更改是模型和迁移以使用 django.contrib.postgres.fields 中的 ArrayField 和 HStoreField 而不是 django_hstore 等效项。

我的猜测是原始代码是错误的,但由于 Django 中的一个错误(过滤器/预取相关)现在已经修复,所以可以正常工作。这可能是正确的吗?如果这实际上是 Django 中的一个 错误,我不想编写依赖它的代码!

【问题讨论】:

    标签: django postgresql django-1.8 django-1.11


    【解决方案1】:

    在 1.8 和 1.9 之间,Django 的字段查找行为发生了变化,这解释了这一点 - 您可以在 Django ticket #25284 上查看详细信息。

    在 Django 1.8 中,Model.objects.filter(related_id = RelatedModel.objects.all()) 之类的查询用于导致隐式 __in 查找,因此 SQL 查询包含 related_id IN (SELECT id FROM ...)。但是在 Django 1.9 中,“IN”被更改为“=”,这会导致查询在 MySql 和 Postgres 中中断。该更改被归类为错误修复,因为隐含的“IN”行为未记录在案并且可能是偶然的。

    您应该能够通过向字段查找添加显式查找类型(例如.filter(project__in=projects))相当容易地修复查询 - 请参阅Django Documentation: Field Lookups

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-10
      • 2021-05-20
      • 2019-03-16
      • 2016-02-26
      • 2015-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多