Django:分组然后通过查询计算列值的总和

Posted

技术标签:

【中文标题】Django:分组然后通过查询计算列值的总和【英文标题】:Django: Group and then Calculate the Sum of the column values through query 【发布时间】:2022-01-04 17:34:27 【问题描述】:

我有一个模型:

lifecycle_status_choice = (
    ('Lead', 'Lead'),
    ('Opportunity', 'Opportunity'),
    ('Customer', 'Customer'),
)
    
bill_status_choice = (
    ('Paid','Paid'),
    ('Pending','Pending'),
    ('Partially Paid','Partially Paid'),
)
class Bill(models.Model):
    company_name    = models.ForeignKey(Contact, on_delete=models.CASCADE)
    grand_tot       = models.DecimalField(max_digits=9, decimal_places=2)
    status          = models.CharField(max_length=100, choices=bill_status_choice)
lifecycle_status    = models.CharField(max_length=100, choices=lifecycle_status_choice) 
    ...

其中有一个 fk 到:

class Contact(models.Model):
    associated_company  = models.CharField(max_length=100) 
    ...

Views.py

...
from bills.models import Bill
from django.db.models import Sum

def home(request):
    data = Bill.objects.all().order_by('date')
    context = 
        'data ':data ,
    
    return render(request, 'home.html',context)

前端图表js:

const ctx = document.getElementById('myChart').getContext('2d');
        const myChart = new Chart(ctx, 
            type: 'doughnut',
            data: 
                labels: [
                    % for data in data % 'data.company_name', % endfor %
            ],
        datasets: [
            label: '# of Votes',
            data: [% for data in data %  data.grand_tot , % endfor %],

问题: 我在前端模板中使用charts.js,我试图显示一个图表,当用户在其中创建新公司名称时,该图表应显示按公司名称分组的总金额我将如何实现?

例如: 我为“xyz”公司创建了两张发票,金额为:100 美元和 200 美元 || & 为“abc”公司创建一张发票,金额为 100 美元 我希望图表对“xyz”发票金额进行分组并显示 300 美元(即:100+200)|| & "abc" = $100

仅供参考,我知道我在视图函数中使用了完全错误的东西,但这只是我尝试过的东西。 谢谢

【问题讨论】:

【参考方案1】:

您可以.annotate(…) [Django-doc] 使用:

from django.db.models import Sum

Contact.objects.annotate(bills_total=Sum('bill__grand_tot'))

由此QuerySet 产生的Contact 对象将具有一个额外的属性.bills_total

您可以使用支付方式过滤此内容:

from django.db.models import Q, Sum

contacts = Contact.objects.annotate(bills_total=Sum('bill__grand_tot', filter=Q(bill__status='Paid')))

因此,您可以使用以下方式渲染它:

% for contact in contacts %
     contact.associated_company :  contact.bills_total 
% endfor %

或者例如将其转换为 Python 字典列表,然后将其作为 JSON blob 返回。

【讨论】:

您好 Willem,您发布的答案引发错误,因为“无法将关键字 'bills_total' 解析为字段。选择是..”,无论如何我也没有看到您已将公司名称分组到任何地方.. .. 你的代码即使运行也会产生的输出,我假设它与我的输出相似,输出每个公司的个人总数而不对它们进行分组 @Ryan:对不起,这是.annotate(..) 而不是.filter(..) @Ryan:至于您发布的视图,这会计算 所有 家公司的Bills 总数,而不是每个 @ 987654332@. 感谢代码运行的更正,但前端没有显示任何内容我已将前端代码添加到原始问题中 @Ryan:您将变量传递为total,而不是data,因此您使用% for data in total % 枚举它。

以上是关于Django:分组然后通过查询计算列值的总和的主要内容,如果未能解决你的问题,请参考以下文章

通过具有最大列值的记录过滤 Django 查询

MySQL 聚合函数 和 分组查询(初级)

MySQL 聚合函数 和 分组查询(初级)

MySQL 聚合函数 和 分组查询(初级)

聚合函数和分组查询(快掏出小本本记下来这些锦囊妙计)

聚合函数和分组查询(快掏出小本本记下来这些锦囊妙计)