DJANGO - 按类别小计和按项目总计

DJANGO - Subtotal by category and total by item

晚上好!

假设我有一个数据库:

Category | Item | Price
Cat1 | Item1 | 
Cat1 | Item2 | 
Cat2 | Item3 | 
Cat2 | Item3 | 
Cat2 | Item4 | 

我想按类别显示总销售额,并在按项目分组的销售明细下方显示

Cat1 - Total Price = 
  Item1 - 
  Item2 - 
Cat2 - Total Price = 
  Item3 -  (the sum of the two item3)
  Item4 - 

我几乎成功了,但我不知道如何按类别进行小计。 我的代码如下:

Model.py

class Category(models.Model):
Category= models.CharField(max_length=100)

class Item(models.Model):
Category= models.ForeignKey(Category, on_delete=models.CASCADE)
Item= models.CharField(max_length=100)

class Order(models.Model):
Category= models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
Item=  models.ForeignKey(Item, on_delete=models.SET_NULL, null=True)
Price=  models.DecimalField()

Views.py

def summary(request):
metrics =  {
'total': Sum('Price'),
}

orders=Order.objects.values('Category','Item').annotate(**metrics))

Template.html

 {% for order in orders%}
       {% ifchanged order.Item%}

       <tr>
           <td>{{ order.Item}} </td>
           <td>{{order.total}} </td>
        </tr>

       {% endifchanged %}
        <tr>
        <td>{{order.Item}}</td>
        <td> {{order.total}}</td>
        </tr>


    {% endfor %}

您可以使用 Prefetch(..) object [Django-doc] 对每个 Category 和每个 Item 进行聚合:

from django.db.models import Prefetch, Sum

def summary(request):
    categories = Category.objects.annotate(
        total=Sum('item__order__Price')
    ).prefetch_related(
        Prefetch(
            'item_set',
            Item.objects.annotate(total=Sum('order__Price')),
            to_attr='items_with_price'
        )
    )
    return render(request, 'template.html', {'categories': categories})

在模板中,可以用以下方式渲染:

{% <b>for category in categories</b> %}
    <tr>
        <td><b>{{ category.Category }}</b></td>
        <td><b>{{ category.total }}</b></td>
    </tr>
    {% <b>for item in category.items_with_price</b> %}
        <tr>
            <td>{{ item.Item }}</td>
            <td>{{ item.total }}</td>
        </tr>
    {% endfor %}
{% endfor %}