Py学习  »  Django

Django如何正确使用骨料

HuLu ViCa • 5 年前 • 1618 次点击  

我有以下型号:

class InvoiceEntry(models.Model):
    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name='entries', verbose_name=_("Invoice"))
    line = models.CharField(max_length=500, verbose_name=_("Print Line"))
    text = models.TextField(null=True, blank=True, verbose_name=_("Print Text"))
    amount = models.PositiveIntegerField(verbose_name=_("Amount"))
    unit_price = models.FloatField(null=True, blank=True, verbose_name=_("Unit Price"))
    content_type = models.ForeignKey(ContentType, on_delete=models.PROTECT, null=True, blank=True, validators=[validate_invoice_target_models])
    object_id = models.PositiveIntegerField(null=True, blank=True)
    is_separator = models.BooleanField(default=False)

我想获取单个发票的总数,因此我使用以下命令获取查询集: invoice_entries = InvoiceEntry.objects.filter(invoice_id=2227) ,如果我申请 values('amount', 'unit_price') ,我得到:

{'amount': 0, 'unit_price': None}
{'amount': 4, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 1, 'unit_price': 11.5}
{'amount': 4, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 1, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 1, 'unit_price': 26.0}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 2, 'unit_price': 11.5}
{'amount': 9, 'unit_price': 23.0}

总共有 七百一十六 ,但当我试图聚合时:

total = InvoiceEntry.objects.filter(invoice_id=2227).aggregate(amount=Sum('amount', field=('amount * unit_price')))

我得到:

{'amount': 52}

我不知道我做错了什么。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/50488
 
1618 次点击  
文章 [ 2 ]  |  最新文章 5 年前
mashgreat
Reply   •   1 楼
mashgreat    6 年前

Django中的F对象允许您进行额外的计算。F对象生成描述数据库级操作的SQL表达式。

试试这个,它应该正确地计算总数。这假设您使用的是Django 1.8+

from django.db.models import Sum, F
InvoiceEntry.objects.filter(invoice_id=2227).aggregate(total=Sum(F('amount') * F('unit_price'))

关于Django中F表达式的更多信息,请参见: https://docs.djangoproject.com/en/2.2/ref/models/expressions/#f-expressions

Durai
Reply   •   2 楼
Durai    6 年前

如果要基于发票进行聚合,则需要使用批注。聚合将处理模型中存在的所有发票。在sql语言中,它类似于下面没有group by。

select sum(column1 * column2) from table;

注释是一种分组方式。

select invoice, sum(column1 * column2) from table group by invoice;

下面的queryset将解决您的问题。

from your_app import models
from django.db.models import F, Sum, FloatField

m = models.InvoiceEntry.objects.values('invoice').annotate(sum=Sum(F('amount') * F('unit_price'), output_field=FloatField()))

<QuerySet [{'invoice': 1, 'sum': 48.0}, {'invoice': 2, 'sum': 8.0}]>

这将提供所有发票金额。如果您需要特定的发票,可以使用过滤器。

m = models.InvoiceEntry.objects.filter(invoice=1).values('invoice').annotate(sum=Sum(F('amount')
* F('unit_price'), output_field=FloatField()))

<QuerySet [{'invoice': 1, 'sum': 48.0}]>