Django:使用前缀sum注释模型

时间:2015-09-03 09:14:51

标签: python django annotate

我有一个模型TimeTrial,它汇总了Leg s的有序列表。

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

enter image description here的精简版。)

TimeTrialManager使用TimeTrial的数量和Leg的总和为每个Leg.duration添加注释。我想以类似的方式使用Django的duration_prefix_sum / annotate来计算aggregate,因此当我在{duration_prefix_sum中显示timetrial.leg_set.all()时,我不会产生数据库命中{1}}。

我知道我可以编写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)

但我宁愿使用注释/聚合/ Case /何时使用Django。

1 个答案:

答案 0 :(得分:0)

我找到了解决方案,但我不确定它是否完全可靠。我implemented it in my project

我们添加过滤器timetrial__leg__order__lte=F('order')以添加包含所有Legs的连接,其顺序小于或等于当前。 然后,我们将注释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'上进行另一个注释/过滤,这将失败,因此欢迎使其更加健壮的附加内容。