如何使用ORM查询对类别进行分组和求和

时间:2019-11-14 21:15:00

标签: django orm

请注意:类似的问题对我没有帮助,因为它们在同一班级中使用了类别-外键。

我有一个带有发票,职位,产品和类别模型的简单发票应用。产品绑定到类别。 我的目标是创建一个查询集

  • 过滤器e。 G。一个特定的日期范围
  • 然后将所有类别分组并建立其总和

这是发票的相应位置的屏幕截图: enter image description here

分组查询的预期结果应如下所示:

enter image description here

您能帮我创建一个查询,对经过过滤的日期范围内的类别进行分组和汇总吗?

我唯一能创建的解决方案是特定日期范围的过滤器:

queryset = Position.objects.filter(invoice__date_of_purchase__range=['2019-01-01', '2019-12-31']) 

models.py(我已经简化了):

from django.db import models
from django.urls import reverse

class Category(models.Model):
    name = models.CharField(max_length=30, unique=True)

    def __str__(self):
        return self.name

class Product(models.Model):
    name = models.CharField(max_length=120)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='products')

    def __str__(self):
        return self.name

class Invoice(models.Model):
    invoice_code = models.CharField(max_length=15)
    date_of_purchase = models.DateField()
    customer_name = models.CharField(max_length=100)

    def __str__(self):
        return self.invoice_code


class Position(models.Model):
    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    quantity = models.DecimalField(decimal_places=2, max_digits=6)
    price = models.DecimalField(decimal_places=2, max_digits=8)
    total = models.DecimalField(
        decimal_places=2, max_digits=8, blank=True, null=True)  # is calculated in view

    def __str__(self):
        return self.product.name

2 个答案:

答案 0 :(得分:2)

以下过滤器将返回在日期范围内具有发票的所有类别,还将过滤注释以仅对这些发票的那些位置求和

categories = Category.objects.filter(
    products__position__invoice__date_of_purchase__range=['2019-11-17', '2019-12-31']
).annotate(
    sum=Sum('products__position__total')
)

每个类别现在都将使用属性“ sum”进行注释

for category in categories:
    print(category, category.sum)

答案 1 :(得分:0)

我将根据我的经验提出一个调整。

  1. 将位置放入多个字段中的发票模型中。这样可以更便宜地过滤发票的日期范围。根据您的用例,它也可能有助于添加“已发送” bol字段。

  2. 在您的视图中或在utils.py文件中。循环遍历查询集的“ Position's”字段,其中类别作为条件以按类别分开,并且+ = Position.total字段分配给您的等待变量。