在Django中编写嵌套查询

时间:2017-12-10 03:37:00

标签: python django

我正在尝试在Django中编写嵌套查询。在SQL中这很简单,但是对于Django,我在确定我是否做得对时遇到了一些麻烦。我有三个型号。 AreaLocationMeasurement

区域

class Area(models.Model):
    name = models.CharField(max_length=200)
    longitude = models.FloatField()
    latitude = models.FloatField()

位置

class Location(models.Model):
    name = models.CharField(max_length=200)
    altitude = models.IntegerField()
    area = models.ForeignKey(Area, on_delete=models.CASCADE)

测量

class Measurement(models.Model):
    value = models.FloatField()
    date = models.DateTimeField()
    location = models.ForeignKey(Location, on_delete=models.CASCADE)

Area内,我需要一个函数来返回该区域的平均测量值。基本上,我需要对该区域的所有位置进行平均测量。 Area可以有多个位置,但位置可以有一个区域。在Area模型中,我实现了这个功能:

def average_measurement(self):
    all_locations = self.location_set.all()
    return all_locations.measurement_set.all().aggregate(Avg('value'))

这相当于在Django中编写嵌套查询。我首先得到所有位置,然后找到他们所有测量的平均值。我这样做了吗?

关于一个问题,这个查询是否等同于这样做:

avg = 0
locations = self.location_set.all()
sum = 0
counter = 0
for l in locations: measurement = l.measurement_set.all()
    if measurement:
        for m in measurement:
           sum += m.value
           counter += 1
if counter != 0:
    avg = sum / counter
return avg

1 个答案:

答案 0 :(得分:2)

使用对象列表时,通常可以直接查询给定模型。所以你可以改用:

def average_measurement(self):
    return Measurement.objects.filter(location__area = self).aggregate(Avg('value'))['value__avg']

您也可以在第二个例子中采用这种方法:

avg = 0
sum = 0
counter = 0
for m in Measurement.objects.filter(location__area = self):
    sum += m.value
    counter += 1
if counter != 0:
    avg = sum / counter
return avg