我的models.py中有以下模型结构,包含Items和Offers:
class Item(models.Model):
STATUS_CHOICES = (
('A', 'Active'),
('C', 'Cancelled'),
)
status = models.CharField(max_length=11, choices=STATUS_CHOICES)
target_amount = models.PositiveIntegerField()
...
class Offer(models.Model)
STATUS_CHOICES = (
('A', 'Active'),
('C', 'Cancelled'),
)
status = models.CharField(max_length=11, choices=STATUS_CHOICES)
amount = models.PositiveIntegerField()
item = models.ForeignKey(Item)
...
我想在views.py中编写一个查询,以获取每个项目的以下内容:
我一直试图用“额外”来实现这个目标(使用postgres):
items = Item.objects.filter(status='A').extra(
select={
'total_amount' : 'select coalesce(sum(amount),0) from myapp_offer where myapp_offer.item_id = myapp_item.id and myapp_offer.status = \'A\'',
'percentage_met' : '(((select coalesce(sum(amount),0) from myapp_offer where myapp_offer.item_id = myapp_item.id and myapp_offer.status = \'A\') / target_amount) * 100)'
}
)
现在第一个选择(total_amount
)正常工作并返回我期望的内容,但percentage_met
始终为0.任何人都可以帮我解释原因吗?
编辑:应该提到我希望能够通过percentage_met
订购答案 0 :(得分:1)
您不需要extra
。只需使用aggregation:
from django.db.models import Sum
items = Item.objects.filter(status='A').annotate(total_amount=Sum('offer__amount'))
无论如何, percentage_met
是每个对象,所以这只是你模型上的一个方法:
class Item(models.Model):
...
@property
def percentage_met(self):
if hasattr(self, 'total_amount'):
return (self.total_amount / float(self.target_amount)) * 100
return None
答案 1 :(得分:1)
我不认为上面的代码是获取所需值的最简洁方法,但是,假设它是 - 我怀疑你看到的问题实际上是SQL中的划分问题 - 一个int / int被覆盖到最近的int,在这种情况下为零。 Sum肯定是一个int;什么是target_amount,它来自哪里?是int吗?
在Postgres中:
select 2/100;
?column?
----------
0
(1 row)
如果是,请投射其中一个值:
select 2::numeric/100;
?column?
------------------------
0.02000000000000000000
(1 row)