【问题标题】:Django: Annotate model with a prefix sumDjango:用前缀和注释模型
【发布时间】:2015-09-03 09:14:51
【问题描述】:

我有一个模型TimeTrial,它聚合了Legs 的有序列表。

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

the actual models 的精简版。)

TimeTrialManagerLegs 的数量和Leg.duration 的总和来注释每个TimeTrial。我想以类似的方式使用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 的 annotate/aggregate/Case/When。

【问题讨论】:

    标签: python django annotate


    【解决方案1】:

    我找到了一个解决方案,但我不确定它是否完全可靠。我有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' 上创建另一个注释/过滤器,这将失败,因此欢迎添加以使其更健壮。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-13
      • 1970-01-01
      • 2012-04-08
      • 2018-03-21
      • 1970-01-01
      相关资源
      最近更新 更多