Django 1.8条件注释导致INNER JOIN而不是LEFT OUTER JOIN

时间:2015-05-17 01:40:13

标签: django django-models django-queryset django-orm django-1.8

模特:

class Bar(GenericModel):
    ...

class Foo(GenericModel):
    bar = models.ForeignKey(Bar, related_name='foo_bar')

查询:

bars = Bar.objects
       .prefetch_related('foo_bar')
       .annotate(sum_foo=Sum(
                             Case(
                                  When(foo_bar__is_deleted=False, then='foo_bar__amount'),
                                  default=Value(0),
                                  output_field=IntegerField()
                                 )
                            )
                )

前者导致内部联接:SELECT ... FROM "bar" INNER JOIN "foo" ON ( "bar"."id" = "foo"."bar_id" ) ...

我打算获得的是LEFT OUTER JOIN("完整列表"用&#34注释的对象; foo.amount"总和,如果" foo&#为0则为0 34;与" bar"相关而不是INNER JOIN?是否可以不回退原始SQL?

2 个答案:

答案 0 :(得分:2)

这是known bug,已在Django 1.8.3(release notes)中更正。

正如您所指出的,问题是正在创建INNER JOIN,当与Bar个对象没有对应关系时,会过滤掉Foo个对象。

使用高于1.8.3的Django版本将解决此问题。

答案 1 :(得分:1)

这种方式似乎正常工作:

bars = Bar.objects
       .prefetch_related('foo_bar')
       .annotate(sum_foo=Sum(
                             Case(
                                  When(Q(foo_bar__is_deleted=False) | Q(foo_bar__is_deleted=None),
                                                 then='foo_bar__amount'),
                                  default=Value(0),
                                  output_field=IntegerField()
                                 )
                            ),
                )