2015-10-28 111 views
1

比方说,我有以下(简化)模型,其中汽车加权。有时候车内有人(但不总是),因此我有一个@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。 显然属性不支持作为参数那里(只有真正的领域是)。

我搜索到了,发现我可能需要使用.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) 

回答

1

尝试:

result = CarWeight.objects.annotate(net_val=Sum('total_weight')-Sum('person_weight')).aggregate(Avg('net_val'),Max('net_val'),Min('net_val')) 
+0

感谢您的帮助了@Anush,我已经更新了我的问题。不幸的是,这不起作用,因为只有具有'person_weight'的对象才会被考虑。 – SaeX

+0

但是,解决方法是将'person_weight'默认设置为“0”而不是空白。既然'blank = True,null = True'原本没有指定,让我接受这个答案。我会相应地更新我的问题。 – SaeX