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 %}],