How can I use Date Range with Sum and Order By in Django

I am working on a project where I have an Income Model with description among other fields as shown below. The description is a choice field and I want to use Date Range to Sum by each description. i.e. I would want to sum all amount for each description and display their total in HTML Template.

Below is what I have tried but I am getting error which says too many values to unpack (expected 2).

Models code:

CATEGORY_INCOME = (
('Photocopy', 'Photocopy'),
('Type & Print', 'Type & Print'),
('Normal Print', 'Normal Print'),
('Color Print', 'Color Print'),
('Passport', 'Passport'),
('Graphic Design', 'Graphic Design'),
('Admission Check', 'Admission Check'),
('Lamination', 'Lamination'),
('Document Scan', 'Document Scan'),
('Email Creation', 'Email Creation'),
('Email Check', 'Email Check'),
('Online Application', 'Online Application'),
('Agreement Form', 'Agreement Form'),
('Envelope / Binding Film', 'Envelope / Binding Film'),
('Web Development ', 'Web Development'),
)

class Income(models.Model): 
    description = models.CharField(max_length=100, choices=CATEGORY_INCOME, null=True)
    staff = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    amount = models.PositiveIntegerField(null=False)
    date = models.DateField(auto_now_add=False, auto_now=False, null=False)
    addedDate = models.DateTimeField(auto_now_add=True)

    class Meta: 
        verbose_name_plural = 'Income Sources'

    def __str__(self):
        return self.description

Views Code

def generate_reports(request):
    searchForm = IncomeSearchForm(request.POST or None)
    searchExpensesForm = ExpensesSearchForm(request.POST or None)
    if request.method == "POST" and searchForm.is_valid() and searchExpensesForm.is_valid():
        listIncome = Income.objects.filter(date__range=[searchForm['start_date'].value(),searchForm['end_date'].value()])
        total_income_passport = listIncome.values('description').order_by('description').annotate(total = Sum('amount')).get('total') or 0
        context = { 'total_income_passport':total_income_passport, }
        return render(request, 'cashier/print_report.html', context)
    else:
        listIncome = Income.objects.all()
    context = { 'listIncome ':listIncome , }
    return render(request, 'cashier/gen_report.html', context)

Please, note that I have no issue with the Date Range but my problem is with Sum by each description in the model. Your kind answer would be much appreciated. thanks

Here is my version of it, following the documentation:

from django.db.models import Sum

def generate_report(request):
    if request.method == 'POST':
        income_form = IncomeSearchForm(request.POST or None)
        expense_form = ExpensesSearchForm(request.POST or None)

        if income_form.is_valid() and expense_form.is_valid():
            start_date = income_form.cleaned_data['start_date']
            end_date = income_form.cleaned_data['end_date']

            grouped_incomes = Income.objects.filter(date__range=[start_date,end_date]).order_by('description')
            grouped_incomes_with_total = grouped_incomes.values('description').annotate(total = Sum('amount')).order_by()

            context = {'incomes': grouped_incomes_with_total}
            return render(request, 'print_report.html', context)

    else:
        income_form = IncomeSearchForm()
        expense_form = ExpensesSearchForm()

    context={
        'income_form': IncomeSearchForm,
        'expense_form': ExpensesSearchForm,
    }

    return render(request, 'generate_report.html', context)
Back to Top