Django: Группировка и последующее вычисление суммы значений столбцов с помощью запроса

У меня есть модель:

    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)
    ...

у которого есть fk to:

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

In my Views.py
...
from bills.models import Bill
from django.db.models import Sum

def home(request):
    total = Bill.objects.filter(status='Paid').aggregate(Sum('grand_tot'))['grand_tot__sum']
    context = {
        'total':total,
    }
    return render(request, 'home.html',context)

Проблема: Я использую charts.js в шаблоне front end и пытаюсь отобразить график, в котором по мере того, как пользователь создает новые названия компаний, график должен отображать общую сумму, сгруппированную по названиям компаний, как мне этого достичь?

Например: Я создаю два счета для компании "xyz" с суммами: $100 & $200 || & создаю один счет для компании "abc" с суммой $100. Я хочу, чтобы график группировал суммы счетов "xyz" и отображал $300 (т.е. 100+200) || & "abc" = $100

FYI Я знаю, что использую что-то совершенно неправильное в функции просмотра, но это просто то, что я пробовал. Спасибо

Вы можете .annotate(…) [Django-doc] с:

from django.db.models import Sum

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

Объекты Contact, возникающие в результате этого QuerySet, будут иметь дополнительный атрибут .bills_total.

Вы можете отфильтровать это с как satus заплатил с:

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.

После попытки нескольких решений я нашел одно, которое работает для меня Я не совсем уверен, что это лучший способ достичь этого, но размещаю его в любом случае на всякий случай, если кто-то может извлечь пользу/помочь улучшить его.

Итак, мои модели остаются неизменными, как указано в вопросе. Мой обновленный views .py выглядит следующим образом:

def home(request):
    contacts = Contact.objects.filter(lifecycle_status='Customer')
    data2 = Bill.objects.values('company_name__associated_company').order_by('company_name__associated_company').annotate(total_price=Sum('grand_tot')).filter(status='Paid')
context = {
        'contacts':contacts,
        'data2':data2,
    }
return render(request, 'home.html',context)

мой фронтенд chartsjs :

const ctx = document.getElementById('myChart').getContext('2d');
        const myChart = new Chart(ctx, {
            type: 'doughnut',
            data: {
                labels: [
                    {% for contacts in contacts %} '{{contacts.associated_company}}', {% endfor %}
            ],
        datasets: [{
            label: '# of Votes',
            data: [{% for data2 in data2 %} {{ data2.total_price }}, {% endfor %}],
Вернуться на верх