pythondjangodecimaldjango-tables2django-money

How to properly aggregate Decimal values in a django app: 'decimal.Decimal' object has no attribute 'aggregate'


I'm in a django-tables2 Table, trying to compute the sum of a column (based on a MoneyField (django-money) in the model, see hereunder):

import django_tables2 as table

class PriceAmountCol(table.Column):
    # print(f"Total price is: {record.price.amount}")
    # print(f"Type of total price is: {type(record.price.amount)}")
    def render(self, value, bound_column, record):
        total_price = record.price.amount.aggregate(
            total=Sum("price")
        )

Class MyTable(table.Table):
    # Fields
    price = PriceAmountCol(
        verbose_name=_("Price [EUR]"),
    )
    #...

But this error is raised:

  File "/code/djapp/apps/myapp/tables.py", line 192, in render
      total_price = record.price.amount.aggregate(
AttributeError: 'decimal.Decimal' object has no attribute 'aggregate'

If not commented out, the two print instructions give:

Total price is: 112.80
Type of total price is: <class 'decimal.Decimal'>

But the value 112.80 is only the first one of the table. There are some others.

How could I properly aggregate price values (Decimal) in my current table column?

The field in the model is as follow:

    price = MoneyField(
        default=0.0,
        decimal_places=2,
        max_digits=12,
        default_currency="EUR",
        verbose_name=_("Price [EUR]"),
    )

Version info

django 4.2.8
djmoney 3.4.1
django-tables2 2.7.0
python 3.10.6

Related information

https://django-tables2.readthedocs.io/en/latest/pages/column-headers-and-footers.html#adding-column-footers
Django-tables2 column total
Django-tables2 footer sum of computed column values


Solution

  • Simply replacing the render() function by:

    class PriceAmountCol(table.Column):
        total_price = 0
        def render(self, value, bound_column, record):
            self.total_price += value
            return value
    

    seems to work. So there is no need to use .aggregate.

    But this solution is maybe(?) less efficient.