在Djang加入两个querysets

2024-05-14 00:19:35 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有以下模型

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查找。

或者是加入奎里塞特家族的其他方式?

注意这是一个简单的例子,我知道对于这个例子,数据库结构可以改进,我只是想说明我的问题。


Tags: getdatemodelmodelssummaryquerydictclass
1条回答
网友
1楼 · 发布于 2024-05-14 00:19:35

解决方案1

尝试使用|连接您的queryset

final_q = q1 | q2

在你的例子中

final_q = summary | awards_used

更新时间:

|不使用计算属性,因此,我们可以先选择queryset,然后映射额外的属性

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))

这个方法有一个问题,你不会得到一个queryset,你会得到一个包含实例的列表。

相关问题 更多 >