Django 查询集。用一个查询注释不同的字段

Django querysets. Annotate different fields with one query

我向数据库写入了 3 个查询以获取不同的值。我需要将这些查询合并为一个查询。

    # Counting Total Number of Plans by Day
    Day.objects.annotate(num_of_plans=Count('plan')) \
        .values('num_of_plans', 'date', 'id')

    # Counting is_completed=True Plans by Day
             Day.objects \
            .filter(plan__is_completed=True) \
            .annotate(num_of_completed_plans=Count('plan__is_completed')) \
            .values('num_of_completed_plans', 'id', 'date')


     # Counting status=deferred Plans by Day
       Day.objects \
            .filter(plan__status='deferred') \
            .annotate(num_of_deferred_plans=Count('plan__is_completed')) \
            .values('num_of_deferred_plans', 'id', 'date')

如您所见,上面有 3 个查询。我需要以某种方式优化此代码并在一个查询的帮助下获取值

型号

class Day(models.Model):
    date = models.DateField(default=datetime.date.today, unique=True)

class Plan(models.Model):
    title = models.CharField(max_length=255)
    status = models.CharField(max_length=255, choices=PLAN_STATUSES, null=True, default='upcoming')
    is_completed = models.BooleanField(default=False, null=True)

    day = models.ForeignKey(Day, CASCADE, null=True)

有什么方法可以优化这 3 个查询并通过一个查询获取值吗?

因为 , you can use the filter=… parameter [Django-doc] in the Count expression. As for the filtering on a Bool, you can just use a Sum expression [Django-doc]:

from django.db.models import Count, Q, Sum

Day.objects.annotate(
    num_of_plans=Count('plan'),
    num_of_completed_plans=<b>Sum('plan__is_completed')</b>,
    num_of_deferred_plans=Count('plan', <b>filter=Q(plan__status='deferred')</b>)
)

通常使用.values()更好。但是利用对象(具有额外的属性),从那时起你就可以保持你在模型上定义的逻辑完好无损。