[英]Django annotate queryset by predicate and count results
I have two models:我有两个模型:
class Game(models.Model):
id = models.AutoField(primary_key=True)
class Score(models.Model):
id = models.AutoField(primary_key=True)
game = models.ForeignKey(Game, related_name="score", on_delete=models.CASCADE)
first_score = models.IntegerField(blank=True)
second_score = models.IntegerField(blank=True)
is_rusk = models.BooleanField(blank=True)
And I got a queryset of Game objects:我得到了一个游戏对象的查询集:
[
{
"id": 314317035,
"score": [
{
"first_score": 5,
"second_score": 1,
"is_rusk": false
}
]
},
{
"id": 311298177,
"score": [
{
"first_score": 5,
"second_score": 2,
"is_rusk": false
}
]
},
{
"id": 310278749,
"score": [
{
"first_score": 5,
"second_score": 2,
"is_rusk": false
}
]
},
{
"id": 309866238,
"score": [
{
"first_score": 5,
"second_score": 0,
"is_rusk": true
}
]
},
{
"id": 307926664,
"score": [
{
"first_score": 5,
"second_score": 0,
"is_rusk": true
}
]
},
{
"id": 306047964,
"score": [
{
"first_score": 4,
"second_score": 5,
"is_rusk": false
}
]
},
{
"id": 304881611,
"score": [
{
"first_score": 5,
"second_score": 3,
"is_rusk": false
}
]
},
{
"id": 304468136,
"score": [
{
"first_score": 5,
"second_score": 2,
"is_rusk": false
}
]
},
]
I want to annotate this queryset with rusks_cnt
, it will be count of objects with is_rusk=True
, If there is a way to not add this to every object, just as one field, that would be good too.我想用rusks_cnt
注释这个查询集,它将是带有is_rusk=True
的对象的计数,如果有办法不将它添加到每个 object 中,就像一个字段一样,那也很好。
I think easiest way to do it like this:我认为最简单的方法是这样的:
cnt = queryset.filter(score__is_rusk=True).count()
But when I'm trying to annotate like this:但是当我试图这样注释时:
cnt = queryset.filter(score__is_rusk=True).count()
queryset = queryset.annotate(cnt=cnt)
It says:它说:
QuerySet.annotate() received non-expression(s): 2.
I've also tried:我也试过:
queryset = queryset.annotate(
rusk_cnt=Sum(
Case(When(score__is_rusk=True, then=1)), output_field=IntegerField()
)
)
But results are:但结果是:
[
{
"id": 279658929,
"rusk_cnt": 1
},
{
"id": 279796553,
"rusk_cnt": null
},
...
]
Also I wondering is just using .count()
will lead to bad performance?另外我想知道只是使用.count()
会导致性能不佳吗?
You can annotate with a Value
:您可以使用Value
进行注释:
from django.db.models import Value
cnt = queryset.filter(score__is_rusk=True).count()
queryset = queryset.annotate(cnt=Value(cnt))
But this will add the same value: the number of Score
objects for the Game
s in the queryset
to all Game
objects, which does not make much sense.但这将添加相同的值:查询集中Game
的Score
对象的queryset
到所有Game
对象,这没有多大意义。
If you want to annotate the Game
objects with True
the number of objects where Score
with is_rusk=True
, you can work with:如果您想用True
注释Game
对象,使用is_rusk=True
Score
的对象数量,您可以使用:
from django.db.models import Q, Sum
queryset.annotate(
rusk_cnt=Sum('score', filter=Q(score__is_rusk=True))
)
Annotate is for calculating on every entry. Annotate 用于计算每个条目。 If you want to calculate for the entire queryset, use Aggregate.如果要计算整个查询集,请使用聚合。
Difference between Django's annotate and aggregate methods? Django的注释和聚合方法之间的区别?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.