2

型号:

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(用“foo.amount”总和注释的“bar”对象的完整列表,如果与“bar”相关的“foo”不存在,则为 0)而不是 INNER JOIN?是否可以不回退到原始 SQL?

4

2 回答 2

2

这是一个已知错误,已在 Django 1.8.3(发行说明)中更正。

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

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

于 2016-05-24T01:23:11.557 回答
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()
                                 )
                            ),
                )
于 2015-05-17T20:18:06.173 回答