[英]Django: Annotate model with a prefix sum
我有一个TimeTrial
模型,该模型汇总了Leg
的有序列表。
class TimeTrial(models.Model):
objects = TimeTrialManager()
class Leg(models.Model):
timetrial = models.ForeignKey(TimeTrial)
duration = models.FloatField()
order = models.PositiveIntegerField(default=0)
@property
def duration_prefix_sum(self):
qs = Leg.objects.filter(timetrial=self.timetrial,
order__lte=self.order)
return qs.aggregate(Sum('duration'))
class TimeTrialManager(models.Manager):
def get_queryset(self):
qs = super(TimeTrialManager, self).get_queryset()
qs = qs.annotate(leg_count=Count('leg'))
qs = qs.annotate(duration=Sum('leg__duration'))
return qs
( 实际模型的精简版。)
所述TimeTrialManager
注释每TimeTrial
与数量Leg
S和的总和Leg.duration
。 我想以类似的方式使用Django的annotate
/ aggregate
来计算duration_prefix_sum
,所以当我在timetrial.leg_set.all()
显示每条腿的duration_prefix_sum
时,不会引起数据库命中。
我知道我可以编写Python代码来计算它:
timetrial.leg_set_annotated = []
s = 0
for l in timetrial.leg_set.all():
s += l.duration
l.duration_prefix_sum_computed = s
timetrial.leg_set_annotated.append(l)
但是我宁愿使用Django的注释/聚合/案例/ When。
我已经找到了解决方案,但是我不确定它是否完全可靠。 我已经在我的项目中实现了它 。
我们添加过滤器timetrial__leg__order__lte=F('order')
来添加包含所有阶数小于或等于当前的timetrial__leg__order__lte=F('order')
。 然后,我们将注释duration_prefix_sum
添加为Sum('timetrial__leg__duration')
,从而计算前缀和。
from django.db.models import Sum, F
qs = Leg.objects.filter(timetrial__leg__order__lte=F('order'))
qs = qs.annotate(duration_prefix_sum=Sum('timetrial__leg__duration'))
我认为,如果使用此查询集的代码在'timetrial__leg'
添加另一个注释/过滤器,则此操作将失败,因此欢迎添加使其更健壮的附加功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.