2016-08-16 75 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