Django在布尔字段上注释

时间:2019-04-12 11:24:05

标签: django postgresql django-queryset

class Forecast(Model):
  id = UUID()
  type = StringField()
  approved = BooleanField()

我想通过在批准的字段上应用“逻辑和”来对字段type进行分组。假设带注释的字段为all_approved。如果所有具有该类型的项目均为True,则all_approved应该为True,如果至少一项为False,则{false}。

因此,最终我希望在查询集中拥有两个字段typeall_approved

我该如何实现?

我尝试了基于this answer的内容,但什么也没得到。

编辑:

当我尝试该答案中给出的内容时,它没有执行“逻辑与”操作。取而代之的是,对于每个type,它只给出两项,一项以all_approved为True,另一项以all_approved为False。我希望每个type都有一个项目。

我也不明白为什么这个答案应该起作用。在哪里指定在分组时是否应该执行“逻辑与”或“逻辑或”。

2 个答案:

答案 0 :(得分:3)

其他解决方案:您可以尝试将所有approvedapproved=True

进行比较
from django.db.models import Count, Case, When, BooleanField

Forecast.objects.values(
    'type'
).annotate(
    cnt_app=Count(Case(When(approved=True, then=1)))
).annotate(
    all_approved=Case(
        When(cnt_app=Count('approved'), then=True),
        default=False,
        output_field=BooleanField()
   )
).values('type', 'all_approved')

其中

Count(Case(When(approved=True, then=1)))为我们提供了类型为True的已批准计数,

Count('approved')给出了该类型的总数,

如果值相等,则all_approved为True,否则为False

答案 1 :(得分:2)

对于具有至少一个all_approved值的类型,您可以使用子查询将False翻转到False

from django.db.models import BooleanField
from django.db.models.expressions import Case, When

(Forecast.objects
    .annotate(all_approved=Case(
        When(type__in=Forecast.objects.filter(approved=False).values('type'), 
             then=False),
        default=True,
        output_field=BooleanField()
    ))
    .values('type', 'all_approved')
    .distinct()
)

您链接的question有点不同,因为它与Django自动加入的两个模型之间的一对多关系有关。

在这里,您只有一个模型,您必须将其自身结合起来才能使用相同的解决方案。由于Django仅支持由关系定义的联接,因此您需要使用子查询作为解决方法。