Django Aggregate对外键的总和

时间:2014-08-21 09:36:34

标签: python sql django sum aggregate-functions

我有以下型号:

class Journey(models.Model):
      time = models.TimeField()
      distance = models.FloatField()

class Trip(models.Model):
      outward_journey = models.ForeignKey(Journey)
      return_journey = models.ForeignKey(Journey, null=True)

现在,如果我有旅行清单,我想知道所有旅行的总行程距离。

E.g。我想要的是总结outward_journey距离和inward_journey距离。 Django是否可以这样(有或没有.extra()声明。我尝试过这样的事情:

 Trip.objects.all().aggregate(out=Sum('outward_journey__distance'), in=Sum('return_journey_distance'))`

这个给了我一个字典,(我可以用Python对这些值求和)但这并不理想,因为return_journey可能为空(对于单程旅行),因此return_journey_distance可能是None。即我可能得到像{'outward_journey_distance' : 500, 'return_journey_distance' : None}

这样的词典

我也尝试过:

Trip.objects.all().extra(select={'distance' : 'SUM(outward_journey.distance) + SUM(inward_journey.distance)'})

但为此,我得到ProgrammingError: missing FROM-clause entry for table "outward_journey"

使用Django ORM完成这样的事情的最简洁方法是什么? (而不是纯粹的原始SQL)?

编辑:

我的另一个想法是在Python中获取距离,然后使用类似的东西对它们求和,但是你可以看到它不理想/不清楚:

 distances = Trip.objects.all().values_list('outward_journey__distance', 'inward_journey__distance')
 # gives distances = ((11, 1), (20, None), (2, 2) ...)
 total_distance = sum([sum([d for d in each_distance if d]) for each_distance in distances)])

1 个答案:

答案 0 :(得分:0)

你可以为此组合2个查询集;一个用于单程旅行,一个用于回程旅行,如下:

round_trips = Trip.objects.exclude(return_journey__distance__isnull=True).aggregate(outward=Sum('outward_journey__distance'), inward=Sum('return_journey_distance'))
oneway_trips = Trip.objects.filter(return_journey__distance__isnull=True).aggregate(oneway=Sum('outward_journey__distance'))

将两者结合起来:

all_distances = dict(round_trips.items() + oneway_trips.items())

或者获得总距离:

total_distance = round_trips.values() + oneway_trips.values()