在Django中组合prefetch_related和annotate

时间:2014-08-19 14:39:26

标签: django django-models django-templates django-views django-queryset

我有三个模特

class ModelA(models.Model):
    name = CharField(max_length=100)

class ModelB(models.Model):
    modela = ForeignKey(ModelA)

class ModelC(models.Model):
    modelb = ForeignKey(ModelB)
    amount = IntegerField()

我可以得到输出

name, number of model c objects
==============
Some name, 312
Another name, 17

使用查询集

ModelA.objects.all().prefetch_related('modelb_set', 'groupb_set__modelc_set')

和模板

{% for modela in modela_list %}
    {% for modelb in modela.modelb_set.all %}
        {{ modelb }}, {{ modelb.modelc_set.count }}
    {% endfor %}
{% endfor %}

我想要对ModelC中的amount字段求和,而不是计算连接到每个ModelB对象的ModelC对象的数量。

我不知道如何在我的查询集中合并prefetch_relatedannotate,但它必须类似于

ModelA.objects.all().prefetch_related('modelb_set', 'groupb_set__modelc_set').annotate(total_amount=Sum('modelc_set__amount'))

2 个答案:

答案 0 :(得分:1)

我认为你应该能够做到这一点:

from django.db.models import F, Sum

ModelA.objects.all()\
    .prefetch_related('modelb_set', 'modelb__modelc_set')\
    .values('name')\ # group values by modela.name, read: https://docs.djangoproject.com/en/1.9/topics/db/aggregation/
    .annotate(name = F('name'),
              total_amount = Sum('modelb__modelc__amount'))

在您的模板中,您应该使用:

{% for modela in modela_list %}
    {{ modela.name }}, {{ modela.total_amount }}
{% endfor %}

答案 1 :(得分:0)

您可以将其简化为:

from django.db.models import F, Sum

ModelA.objects.all()
    .prefetch_related('modelb__modelc_set') \
    .values('name') \
    .annotate(name=F('name'), total_amount=Sum('modelb__modelc__amount'))

我知道这适用于更高版本的 Django。