2012-06-05 48 views
1

我在我的models.py下面的模型結構,項目和優惠:Django的「額外」的查詢

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. 已針對此項目滿足由優惠(靶的百分比,即/ TARGET_AMOUNT * 100 [由式(1)的總] )

我一直在試圖與「額外」來實現這一如下(使用的是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任何人都可以幫我解答爲什麼?

編輯:應該提到,我希望能夠在ORDER_BY percentage_met

回答

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 
+0

這是真實的,但麻煩的是我想ORDER_BY percentage_met ..只是嘗試這樣做,我不似乎無法order_by財產:/ – JimJay

+0

好吧,不要擔心..已經計算出如何使用sorted()按照http://stackoverflow.com/questions/981375/using-a- django-custom-model-method-property-in-order- – JimJay

1

我不認爲上面的代碼是得到最徹底的方法你想要的值,但是,假設它是 - 我懷疑你看到的問題實際上是SQL中的一個問題 - 一個int/int獲取到最近的int,在這種情況下是零。總和肯定是一個整數;什麼是target_amount,它來自哪裏?它是一個int嗎?

在Postgres裏:

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

如果是這樣,投中的一個值:

select 2::numeric/100; 
?column?   
------------------------ 
0.02000000000000000000 
(1 row) 
+0

這正是問題所在,謝謝。再看一遍,雖然我會同意,我試圖做到這一點的方式不乾淨,必須有一個更簡單的方法... – JimJay