Django升级filter / prefetch_related行为更改?

时间:2018-09-27 17:54:41

标签: django postgresql django-1.8 django-1.11

我正在从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]

当[项目查询]返回多行时,此操作中断。所以我得到一个:

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

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

我的猜测是原始代码是错误的,但由于Django中的一个错误(filter / prefetch_related)而得以解决,该错误现已修复。那可能是正确的吗?如果实际上这是Django中的 new 错误,我不想编写依赖它的代码!

1 个答案:

答案 0 :(得分:1)

Django在1.8和1.9之间的字段查找行为发生了变化,这解释了这一点-您可以在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

,您应该能够相当轻松地解决查询问题。