请考虑以下内容:
class Fighter(models.Model):
...
#a bunch of fields
class View(models.Model):
fighter = models.ForeignKey(Fighter,on_delete=models.CASCADE, related_name="views")
viewer = models.ForeignKey(User,on_delete=models.PROTECT, related_name="viewed") #User.viewed.all() returns all View objects of the Fighters the user viewed
class Clash(models.Model):
win_fighter = models.ForeignKey(Fighter,on_delete=models.SET_NULL, related_name="wins")
loss_fighter = models.ForeignKey(Fighter,on_delete=models.SET_NULL, related_name="losses")
这里的关键是fighter_quality = wins / views = Fighter.wins.all()。count()/ Fighter.views.all()。count() 我需要能够过滤这种质量,例如所有50%<质量<80%的战斗机。我希望我的Postgres DB能够完成工作。
我觉得应该可以通过Aggregate
来实现,但不知道如何...
答案 0 :(得分:2)
您可以.annotate(..)
使用该质量指标的战斗机,然后按照给定的范围进行过滤,例如:
from django.db.models import Count, ExpressionWrapper, FloatField
Fighter.objects.annotate(
quality=ExpressionWrapper(
Count('wins', distinct=True)/Count('views', distinct=True),
output_field=FloatField()
)
).filter(
quality__range=(0.5, 0.8)
)
distinct=True
是必需的,因为否则质量始终为1
:实际上,由于我们进行了两个JOIN,并且我们计算了id
中的View
和id
中的Win
个,但这些数字始终匹配。
因此,quality__range=(0.5, 0.8)
将使用__range
查找(其中下限为quality
,上限为0.5
(包括两者)筛选0.8
注释
ExpressionWrapper(..., outputField=FloatField())
是必需的,以便Django理解quality
是浮点数,否则它将将0.5
和0.8
转换为int
,因此检查0
和0
之间的值。