使用 Django 聚合求和

发布于 2024-08-26 15:40:28 字数 1449 浏览 6 评论 0原文

问题

背景

我正在对发票建模,其中可以包含多个项目。 Invoice 和 Item 模型之间的多对多关系是通过 InvoiceItem 中间表处理的。

发票总金额 - amount_invoiced - 是通过将给定发票上每件商品的 unit_pricequantity 的乘积相加来计算的。下面是我目前用来完成此操作的代码,但我想知道是否有更好的方法使用 Django 的聚合功能

当前代码

class Item(models.Model):
    item_num = models.SlugField(unique=True)
    description = models.CharField(blank=True, max_length=100)


class InvoiceItem(models.Model):
    item = models.ForeignKey(Item)
    invoice = models.ForeignKey('Invoice')
    unit_price = models.DecimalField(max_digits=10, decimal_places=2)
    quantity = models.DecimalField(max_digits=10, decimal_places=4)


class Invoice(models.Model):
    invoice_num = models.SlugField(max_length=25)
    invoice_items = models.ManyToManyField(Item,through='InvoiceItem')

    def _get_amount_invoiced(self):
        invoice_items = self.invoiceitem_set.all()
        amount_invoiced = 0
        for invoice_item in invoice_items:
            amount_invoiced += (invoice_item.unit_price *
                invoice_item.quantity)
        return amount_invoiced

    amount_invoiced = property(_get_amount_invoiced)        

Question

Background

I am modeling an invoice, which can contain multiple items. The many-to-many relationship between the Invoice and Item models is handled through the InvoiceItem intermediary table.

The total amount of the invoice—amount_invoiced—is calculated by summing the product of unit_price and quantity for each item on a given invoice. Below is the code that I'm currently using to accomplish this, but I was wondering if there is a better way to handle this using Django's aggregation capabilities.

Current Code

class Item(models.Model):
    item_num = models.SlugField(unique=True)
    description = models.CharField(blank=True, max_length=100)


class InvoiceItem(models.Model):
    item = models.ForeignKey(Item)
    invoice = models.ForeignKey('Invoice')
    unit_price = models.DecimalField(max_digits=10, decimal_places=2)
    quantity = models.DecimalField(max_digits=10, decimal_places=4)


class Invoice(models.Model):
    invoice_num = models.SlugField(max_length=25)
    invoice_items = models.ManyToManyField(Item,through='InvoiceItem')

    def _get_amount_invoiced(self):
        invoice_items = self.invoiceitem_set.all()
        amount_invoiced = 0
        for invoice_item in invoice_items:
            amount_invoiced += (invoice_item.unit_price *
                invoice_item.quantity)
        return amount_invoiced

    amount_invoiced = property(_get_amount_invoiced)        

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绅刃 2024-09-02 15:40:28

是的,从 Django 1.1 开始就引入了聚合函数,这是可能的。这是适合您的模型的解决方案:

 def _get_amount_invoiced(self):
     self.invoiceitem_set.extra(select=("item_total": "quantity * unit_price")
                                ).aggregate(total=Sum("item_total")["total"]

但是,强烈建议将 item_total 存储在数据库中,因为它可能会受到折扣、税收和其他变化的影响,从而使得每次计算它不切实际甚至不可能。

Yes, it is possible since Django 1.1 where aggregate functions were introduced. Here's a solution for your models:

 def _get_amount_invoiced(self):
     self.invoiceitem_set.extra(select=("item_total": "quantity * unit_price")
                                ).aggregate(total=Sum("item_total")["total"]

It is, however, highly recommended to store item_total in a database, because it may be subject to discounts, taxes and other changes that make calculating it evety time impractical or even impossible.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文