我正在使用Django 2.2
在制作查询集时,我希望根据一些条件来计算相关模型
queryset = self.model.objects.filter(user=self.request.user).annotate(
count_videos=Count('video'),
count_completed=Count(
Case(
When(video__status__in=Video.STATUS_LIST_COMPLETED)
)
),
count_failed=Count(
Case(
When(video__status__in=Video.STATUS_LIST_FAILED)
)
),
count_pending=Count(
Case(
When(
video__status__not_in=Video.STATUS_LIST_PENDING_EXCLUDE
)
)
)
)
这里有3个计数有效,但是在最后一个计数count_pending
中,我必须计数为exlude()
。即,对不包括传递的列表在内的记录数进行计数。
如何将exclude
与上述声明一起使用?
答案 0 :(得分:2)
我们可以否定传递给filter=
parameter [Django-doc]的值:
from django.db.models import Count, Q
queryset = self.model.objects.filter(user=self.request.user).annotate(
count_videos=Count('video'),
count_completed=Count(
'video',
filter=Q(video__status__in=STATUS_LIST_COMPLETED)
),
count_failed=Count(
'video',
filter=Q(video__status__in=Video.STATUS_LIST_FAILED)
),
count_pending=Count(
'video',
filter=~Q(video__status__in=Video.STATUS_LIST_PENDING_EXCLUDE)
)
)
这将导致如下查询:
SELECT model.*,
COUNT(
CASE WHEN NOT video.status IN STATUS_LIST_PENDING_EXCLUDE
AND video.status IS NOT NULL
THEN video.id
ELSE NULL END
) AS count_pending
FROM model
LEFT OUTER JOIN video ON model.id = video.model_id
GROUP BY model.id
答案 1 :(得分:0)
很抱歉回复了一个非常老的问题,但这个问题在搜索此主题时的命中率很高。我需要一个非常相似的东西并想要一个计数,但有一些奇怪的条件我无法用 ~Q
解决并登陆一个注释,如下所示。在这里发布仅适用于碰巧需要类似东西的人。
我需要对已完成和正在进行的评论进行计数,但如果 review.status
未受影响,则不会在“进行中”或“已完成”箱中计数。我使用 Case 并将“非”条件(未完成)的默认值设置为 1,然后将 Case 包装在 Sum 中,如图所示。大约有 9 种不同的状态表示“进行中”,我不想一一列举。
.values(___bunch_of_group_by_fields_here___)\
.annotate(
completed=Sum(Case(
When(status__in=[Review.REVIEW_COMPLETE,
], then=Value(1)),
default=Value(0),
output_field=IntegerField(),
)),
# essentially: ( not (review complete or untouched) )
# gets all the status between untouched (default first step) and
# complete (final status in the workflow for a review) without having
# to specify all the in between statuses
inprogress=Sum(Case(
When(status__in=[Review.REVIEW_COMPLETE,
Review.UNTOUCHED
], then=Value(0)),
default=Value(1),
output_field=IntegerField(),
))