1

我的 models.py 中有以下模型结构,包含项目和优惠:

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 中编写一个查询来为每个项目获取以下信息:

  1. 此项目的当前(有效)报价总数
  2. 此项目的报价已达到目标的百分比(即[来自 (1) 的总数]/target_amount * 100)

我一直在尝试通过“额外”来实现这一点,如下所示(使用 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)'
    }
)

现在第一个 select ( total_amount) 工作正常并返回我所期望的,但percentage_met始终为 0。谁能帮我解释为什么?

编辑:应该提到我希望能够 order_by the percent_met

4

2 回答 2

1

你不需要extra这个。只需使用聚合

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
于 2012-06-05T19:37:04.023 回答
1

我不认为上面的代码是获得你想要的值的最干净的方法,但是,假设它是——我怀疑你看到的问题实际上是 SQL 中的除法问题——一个 int /int 被设置为最近的 int,在这种情况下为零。Sum 肯定是一个 int;什么是 target_amount,它来自哪里?它是一个整数吗?

在 Postgres 中:

select 2/100; 
?column? 
----------
        0
(1 row)

如果是这样,请转换以下值之一:

select 2::numeric/100;
?column?        
------------------------
 0.02000000000000000000
(1 row)
于 2012-06-05T19:38:18.637 回答