我有两个模型:
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)
我得到了一个游戏对象的查询集:
[
{
"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
}
]
},
]
我想用rusks_cnt
注释这个查询集,它将是使用is_rusk=True
的对象计数,如果有一种方法可以不将它添加到每个对象,就像一个字段一样,那也会很好。
我认为最简单的方法是:
cnt = queryset.filter(score__is_rusk=True).count()
但是当我尝试这样注释的时候:
cnt = queryset.filter(score__is_rusk=True).count()
queryset = queryset.annotate(cnt=cnt)
上面写着:
QuerySet.annotate() received non-expression(s): 2.
我也尝试过:
queryset = queryset.annotate(
rusk_cnt=Sum(
Case(When(score__is_rusk=True, then=1)), output_field=IntegerField()
)
)
但结果是:
[
{
"id": 279658929,
"rusk_cnt": 1
},
{
"id": 279796553,
"rusk_cnt": null
},
...
]
我还想知道仅仅使用.count()
会导致糟糕的性能吗?
发布于 2021-12-03 22:07:38
Annotate用于对每个条目进行计算。如果您想要计算整个查询集,请使用聚合。
发布于 2021-12-03 22:04:34
您可以使用Value
进行注释
from django.db.models import Value
cnt = queryset.filter(score__is_rusk=True).count()
queryset = queryset.annotate(cnt=Value(cnt))
但是这将添加相同的值:将queryset
中的Game
的Score
对象的数量添加到所有Game
对象中,这没有多大意义。
如果您要使用Game
True
Score
is_rusk=True
中的对象数量来注释对象,可以使用:
from django.db.models import Q, Sum
queryset.annotate(
rusk_cnt=Sum('score', filter=Q(score__is_rusk=True))
)
https://stackoverflow.com/questions/70221083
复制相似问题