假设我有跟随(简化)模型,其中Car是加权的。有时车内有人(但并非总是如此),因此我有@property
来计算汽车的net_weight
。
class CarWeight(models.Model):
total_weight = models.DecimalField(max_digits=5, decimal_places=1)
person_weight = models.DecimalField(max_digits=5, decimal_places=1, null=True, blank=True)
@property
def net_weight(self):
if self.person_weight:
return self.total_weight - self.person_weight
else:
return self.total_weight
def __unicode__(self):
if self.person_weight > 0:
return u"%s (excl. persons)" % (self.total_weight - self.person_weight)
else:
return u"%s" % self.total_weight
现在,我想获得CarWeight
个对象的最小,最大和平均净重。
我以为我可以CarWeight.objects.aggregate(Avg('net_weight'), Max('net_weight'), Min('net_weight'))
,但这会产生Cannot resolve keyword 'net_weight' into field
。
显然,不支持属性作为参数(仅实际字段)。
我搜索了SO,发现我可能需要使用.extra()
,但无法让它发挥作用。
注意:我不想反规范化(通过存储net_weight并覆盖save()
)。
使用Django 1.8和Postgres。
修改
正如所建议的那样,当我首先尝试使用聚合然后进行注释时,我会得到错误的结果:
>>> CarWeight.objects.all()
[<CarWeight: 100.0>, <CarWeight: 120.0>]
>>> CarWeight.objects.annotate(net_val=Sum('total_weight')-Sum('person_weight'))
[<CarWeight: 100.0>, <CarWeight: 120.0>]
>>> CarWeight.objects.annotate(net_val=Sum('total_weight')-Sum('person_weight')).aggregate(Avg('net_val'), Max('net_val'), Min('net_val'))
{'net_val__avg': None, 'net_val__max': None, 'net_val__min': None}
>>> CarWeight.objects.create(total_weight=500, person_weight=100)
<CarWeight: 400 (excl. persons)>
>>> CarWeight.objects.annotate(net_val=Sum('total_weight')-Sum('person_weight')).aggregate(Avg('net_val'), Max('net_val'), Min('net_val'))
{'net_val__avg': 400.0, 'net_val__max': Decimal('400.0'), 'net_val__min': Decimal('400.0')}
>>> CarWeight.objects.annotate(net_val=Sum('total_weight')-Sum('person_weight'))
[<CarWeight: 400.0 (excl. persons)>, <CarWeight: 100.0>, <CarWeight: 120.0>]
EDIT2 :
此方法的解决方法是默认情况下将person_weight设置为“0”而不是空。然后计算可以毫无问题地进行。
person_weight = models.DecimalField(max_digits=5, decimal_places=1, default=0)
答案 0 :(得分:1)
尝试:
result = CarWeight.objects.annotate(net_val=Sum('total_weight')-Sum('person_weight')).aggregate(Avg('net_val'),Max('net_val'),Min('net_val'))