Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 减少Django中的查询数量_Python_Django - Fatal编程技术网

Python 减少Django中的查询数量

Python 减少Django中的查询数量,python,django,Python,Django,我正在创建一个Django应用程序来跟踪一个人获得的奖励。以下是我拥有的两个模型的简化表示: class AwardHolder(models.Model): name = models.CharField() def get_total_awards(self): entries = self.award_set.all() calc = entries.aggregate(sum=Sum('units_awarded')) r

我正在创建一个Django应用程序来跟踪一个人获得的奖励。以下是我拥有的两个模型的简化表示:

class AwardHolder(models.Model):
    name = models.CharField()

    def get_total_awards(self):
        entries = self.award_set.all()
        calc = entries.aggregate(sum=Sum('units_awarded'))
        return calc.get('sum') or 0


class Award(models.Model)
    date_awarded = models.DateField()
    units_awarded = models.IntegerField()
    award_holder = models.ForeignKey(AwardHolder)
我为获奖者创建了一个摘要页面,在那里他可以看到他的全部奖项。我使用上面的
get\u total\u awards
功能。这一切都很好,但后来我创建了一个概述页面来显示每个获奖者的总奖项。我使用以下功能获得每位获奖者的总奖项:

def get_all_awards():
    qs = AwardHolder.objects.all()
    awards = []
    for ah in qs:
        awards.append((ah, ah.get_total_awards())
    return awards
这会生成大量查询,因为它每次都会命中db循环。有没有一种方法可以使用
prefetch\u related
或其他一些数据库技巧来减少数据库查询的数量,而不必重写
get\u all\u awards()


我使用的实际代码有很多字段,比这个示例更复杂。大约有10个函数类似于
get\u all\u awards()
,因此重写它将是一项相当艰巨的工作。然而,对于100名获奖者,我的代码生成了高达18000个查询,因此我知道我必须以某种方式解决这个问题。

获取所有奖项
不一定要调用
获取总奖项
。您对每个实体重复相同的查询,而不是使用Django已经提供的功能:
annotate

仅当奖励应用于单个实体时,您可以修改
get_all_awards
以使用
annotate
并使用
get_total_awards

def get_all_awards():
    qs = AwardHolder.objects.annotate(sum=Sum('award__units_awarded'))
    awards = []
    for ah in qs:
        awards.append((ah, ah.sum))
    return awards
您甚至可以删除
for
循环,直接使用queryset
qs
的结果


因此,在获取多个对象及其相关对象时,您可以利用优化查询的优势,而不是为每个实体运行单独的查询。

使用模型管理器始终为获奖者添加注释。

class AwardHolderQuerySet(models.QuerySet):
    def all(self):
        return self.annotate(Count('award__units_awarded'))

class AwardHolder(models.Model):
    name = models.CharField()
    objects = AwardHolderQuerySet.as_manager()
    ...

我认为这是一项注释而不是聚合的工作。类似于
AwardHolder.objects.annotate(Count('award\u units\u designed'))
我希望避免这种情况,因为我需要重做很多功能。如果我只想知道单个获奖者的获奖数量,我想AwardHolder中的get_total_awards函数仍然适用?对于单个获奖者,该函数是完美的,除非您可以以某种方式拥有少于1个查询:P对于较大的数字,最好在单个查询中执行所有操作,而不是循环并执行多个查询查询,但您需要测试
annotate
是否确实像我认为的那样