Django aggregation. How to render its value into the template?

Question:

I have came across on one of the weirdest problem which I literally can’t understand. Well I was following This, but nothing helped.
As the question says, I just want to render the result into the template. Below is my code.

Views.py

...
    invoice = lead.invoice_set.all()
    total_invoice = invoice.aggregate(total=Sum('amount'))

    context = { 'total_invoice' : total_invoice }

html

{{total_invoice.total}}

This is my code which according to the documentation has to work and as it suggested on the link I’ve shared. Unfortunately, Its not working for I don’t know what reason.
Below is what I’ve tried so far.

TRY 1

When I try to print this into terminal it brings me a dictionary. for example.

print(total_invoice)

prints on terminal...
{'total': 70000}

Which is quite understandable. Now I would want to extract the value and that can be done by simple {{total_invoice.total}}. But it shows nothing on the template.

TRY 2 (Working)

Since I was trying different ways to render the value into the template, I came across this weird solution. I don’t know how is this working.
What I did different from TRY 1 here is just changing the variable name(total_invoice) to (total) and it worked perfectly fine. Here its how.

Views.py

    invoice = lead.invoice_set.all()
    total = invoice.aggregate(total=Sum('amount'))

    context = { 'total' : total }

html

{{total.total}}

Here its perfectly working by just changing the variable name to total. But then I thought that the name should be same but that’s not the case so I tried giving same name to both the variables but this time something other then ‘total’ but again it did not work. for example

...
total_invoice = invoice.aggregate(total_invoice =Sum('amount'))

What is literally going on I have no idea.

Can any one help me with this.
Thank you

Asked By: Muhammed Mahir

||

Answers:

If you aggregate, you obtain a dictionary. Indeed, you see:

{'total': 70000}

You can access the value that corresponds to a key by using {{ variable_name.key }} in the Django template.

So if you pass it with:

    …
    total_invoice = invoice.aggregate(total_invoice=Sum('amount'))
    …
    render(request, 'some_template.html', {'total_invoice': total_invoice })

then in the template, you render it with:

{{ total_invoice.total_invoice }}

the part before the dot refers to the variable name: the name in the dictionary (in italics), and the second to the key in the dictionary (in boldface).

If you thus pass it through a variable named total:

    …
    total_invoice = invoice.aggregate(total_invoice=Sum('amount'))
    …
    render(request, 'some_template.html', {'total': total_invoice })

you render it with:

{{ total.total_invoice }}

It might however be more sensical to unpack the dictionary in the view, and thus pass the total as one variable:

    …
    total_invoice = invoice.aggregate(total=Sum('amount'))['total']
    …
    render(request, 'some_template.html', {'total_invoice': total_invoice })

and then render it with:

{{ total_invoice }}
Answered By: Willem Van Onsem

The answer may no longer be needed but I’ll give my answer to help those who might look for this in the future.

Generating summary values over an entire QuerySet using aggregate() clause gives a Python dictionary:

>>> total_invoice = invoice.aggregate(total=Sum('amount'))
>>> total_invoice
{'total': 70000}

Therefore, to obtain the value 70000, just use the standard way of getting a value using a key like below

>>> total_invoice['total']
70000

So you’ll have

render(request, 'some_template.html', {'total_invoice': total_invoice['total']})

And then in your HTML just render it with

{{ total_invoice }}
Answered By: Evance Odoyo