[英]Django annotate queryset by predicate and count results
我有兩個模型:
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
的對象的計數,如果有辦法不將它添加到每個 object 中,就像一個字段一樣,那也很好。
我認為最簡單的方法是這樣的:
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()
會導致性能不佳嗎?
您可以使用Value
進行注釋:
from django.db.models import Value
cnt = queryset.filter(score__is_rusk=True).count()
queryset = queryset.annotate(cnt=Value(cnt))
但這將添加相同的值:查詢集中Game
的Score
對象的queryset
到所有Game
對象,這沒有多大意義。
如果您想用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 用於計算每個條目。 如果要計算整個查詢集,請使用聚合。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.