如何处理Django中的大型查询集

时间:2017-05-15 06:36:00

标签: python django postgresql

我需要在Django中处理大约15 000行的查询集。我基本上遍历查询集并从查询集中的每个对象创建一个新对象。新对象包含许多计算字段,如下所示。然后将报告的结果保存为Excel文件,每个CalcEntry都有一行。

def get_report(report_date):
    for db_entry in my_large_queryset:
        yield CalcEntry(db_entry, report_date)

class CalcEntry(object):
    def __init__(self, db_entry, report_date):
        self.db_entry = db_entry
        self.report_date = report_date

    @property
    def calc1(self):
        if self.db_entry.value_date > self.report_date
            return self.db_entry.value
        return 0

    @property
    def calc2(self):
        #... There's about 20 of these calcs in the CalcEntry class

创建报告大约需要20秒,所以我很快就会收到超时错误,因为它在Heroku上运行(Heroku在30秒后超时)。但是,只是循环遍历查询集需要花费大量时间,甚至不需要创建CalcEntry类。我读到不建议循环使用大型查询集,但我认为大的会超过15 000。

看起来不是循环查询集,我应该使用values()方法。因此,我想到了以下解决方案,但所有这些都需要大量的工作,所以我希望还有另一种更好的方法来处理这个问题:

  1. 尝试使用F表达式计算字段,然后在查询集上使用值()。这会导致怪物查询。
  2. 在后台运行计算并将其保存在特定报告日期的新数据库表中。同样在这种情况下,我可以使用values()方法获取可用于创建Excel文件的字典列表。
  3. 做一些原始的SQL计算,但我想尽可能避免这种情况(我使用postgreSQL)
  4. 人们通常如何处理大型查询集以及可用于循环查询集的其他替代方法?

1 个答案:

答案 0 :(得分:2)

同意评论,更多细节将有所帮助。

然而,取而代之的是,有人会考虑将这些计算结果转化为模型字段。例如,如果您循环的对象是名为Rectangle的模型,如下所示:

class Rectangle(models.Model):
    name = models.CharField()
    side1 = models.IntegerField()
    side2 = models.IntegerField()

如果您希望使用每个Rectangle的区域周边来吐出Excel文件,您可以再添加两个字段:

area = models.IntegerField()
perimeter = models.IntegerField()

在创建矩形时计算,而不是在制作Excel工作表时计算它们时所执行的操作。对于您已经拥有的项目,您可以更新新字段的模型,然后编写一个脚本进行一次性计算以填充它们。

这样你就可以打电话了

Rectangle.objects.all().values('name', 'area', 'perimeter')

获得你想要的东西。