2016-08-16 107 views
2

假設我有以下型號連接兩個查詢集Django的

class Award(models.Model): 
    user = models.ForeignKey(User) 


class AwardReceived(models.Model): 
    award = models.ForeignKey(award) 
    date = models.DateField() 
    units = models.IntegerField() 


class AwardUsed(models.Model): 
    award = models.ForeignKey(award) 
    date = models.DateField() 
    units = models.IntegerField() 

現在,假設我想獲得的獎項爲所有用戶的數量和用於所有用戶(即包含queryset的獎項數目都)。我更喜歡爲每次計算都做一個查詢 - 當我將它合併到代碼中時,我得到了一些意想不到的結果。此外,對於我的一些查詢,將不可能做到一個查詢,因爲查詢會變得太複雜 - 我計算8個字段。這是我如何解決它至今:

def get_summary(query_date) 
    summary = (Award.objects.filter(awardreceived__date__lte=query_date)) 
        .annotate(awarded=Sum('awardissuedactivity__units_awarded'))) 

    awards_used = (Award.objects.filter(awardused__date__lte=query_date) 
         .annotate(used=Sum('awardused__date__lte__units'))) 

    award_used_dict = {} 
    for award in awards_used: 
     award_used_dict[award] = award.used 

    for award in summary: 
     award.used = award_used_dict.get(award, 0) 

    return summary 

我敢肯定,必須有解決這個不字典方法的方法嗎?例如,像這樣的:awards_used.get(award=award),但這會導致每個循環的db查找。

或者其他一些奇特的方式來加入查詢集?

請注意這是一個簡化的例子,我知道這個例子的數據庫結構可以改進,我只是想說明我的問題。

+0

考試中的'exercised_awards_dict'是什麼? –

+0

對不起,我從我的代碼複製,但沒有更改所有變量名 - 現在修復它 – Johan

回答

5

SOLUTION 1

剛剛嘗試使用|

final_q = q1 | q2 

在您的例子

final_q = summary | awards_used 

更新到您的級聯查詢集:

|不計算使用屬性的作品,所以,我們可以先選擇我們的查詢集映射我們的額外屬性

summary = Award.objects.filter(awardreceived__date__lte=query_date) 
awards_used = Award.objects.filter(awardused__date__lte=query_date) 
final_q = summary | awards_used 

final_q = final_q.annotate(used=Sum('awardused__date__lte__units')).annotate(awarded=Sum('awardissuedactivity__units_awarded')) 

解決方案2

使用鏈內置功能

from itertools import chain 
final_list = list(chain(summary, awards_used)) 

有是這個方法的問題,你不會得到一個查詢集,你會得到一個包含實例的列表。

+0

如果我然後使用final_q [0] .used我得到一個屬性錯誤。這就好像使用|時不包括計算的值 – Johan

+0

@Johan我更新了我的答案 – levi

+0

非常感謝,我會試試看。不介意列出清單 – Johan