【问题标题】:Django queryset optimisation: Reverse lookup on _set with filterDjango 查询集优化:使用过滤器对 _set 进行反向查找
【发布时间】:2017-06-28 10:02:32
【问题描述】:

我有这些模型,我需要做一些计算并将它们呈现给用户。我渲染了大约 2-3k 行,这导致对数据库执行 4k 次查询(从调试工具栏显示)。有没有办法优化这个?我已经尝试过使用 prefetch_related 但它只是在 4k 之上添加了另一个正在完成的查询..

class Cart(models.Model):
    name = models.CharField(max_length=15)
    user = models.OneToOneField(User)


    def sum_for_this(self, taxtype, tax):
        return self.carttax_set.filter(tax__type__name=taxtype,
                                       tax__tax=tax).aggregate(
            sum=Coalesce(Sum('tax_amount'), Value('0'))
        ).get('sum')


class TaxType(models.Model):
    name = models.CharField(max_length=10)


class Tax(models.Model):
    name = models.CharField(max_length=100)
    type = models.ForeignKey(TaxType)
    tax = models.DecimalField()


class CartTax(models.Model):
    cart = models.ForeignKey(Cart)
    tax = models.ForeignKey(Tax)
    base = models.IntegerField()
    tax_amount = models.IntegerField()

我在模板中做的是:

{% for cart in cartlist %}
{{ cart.sum_for_this }}
{% endfor %}

我试过了,但没有效果:

Cart.objects.prefetch_related('carttax_set').all()

def sum_for_this 方法正在执行所有查询..

【问题讨论】:

  • 您可以尝试使用 Prefetch 过滤您获取的查询集,然后在 Python 中进行求和,而不是使用聚合。

标签: python django postgresql


【解决方案1】:

尝试使用conditional expressions 进行注释。您的查询将如下所示:

from django.db.models import Q, F, Sum, Case, When, IntegerField
from django.db.models.functions import Coalesce


cartlist = Cart.objects.annotate(
    sum=Coalesce(Sum(Case(
        When(Q(carttax__tax__type__name=taxtype) & Q(carttax__tax__tax=tax), then=F('carttax__tax_amount')),
        output_field=IntegerField()
        )), 0)
    )

在模板中:

{% for cart in cartlist %}
{{ cart.sum }}
{% endfor %}

【讨论】:

  • 这将缩小我的查询范围。我需要按用户过滤的数据(编辑我的问题),然后尝试这些注释合并或聚合...
  • 什么意思?
  • 我需要返回属于 User 的所有 Cart 对象,然后进行计算。这将根据 carttax_set__tax__type__name afaik 过滤它们
  • 我收到了这个回复:Cannot resolve keyword carttax_set... Choices are 'name' & 'user'..
  • 抱歉回复晚了,我已经修复了我的答案,现在应该可以了。
猜你喜欢
  • 2014-12-10
  • 2015-02-09
  • 2017-06-24
  • 1970-01-01
  • 2019-07-21
  • 2018-11-08
  • 2014-10-03
  • 2015-08-18
相关资源
最近更新 更多