0

Is there a way to get the sum of values of a column which contains computed values? I tried rendering the footer following the documentation and a question here, but without results.

EDIT:

class BillsColumn(Column):
    def render(self, record):
        bills = record.certificatebills.all()
        total_bill = 0
        for bill in bills:
            total_bill += bill.bill_amount
        return(round(total_bill, 2))

    def render_footer(self, bound_column, table):
        column_values = sum(columns_somehow)
        return column_values

This is the custom column I'm using. It returns the sum of certificate bills of of each certificate and then shows it in the Column. I don't know how to access this computed value in the render_footer method.

Jordan Mora
  • 889
  • 6
  • 16

1 Answers1

1

You could accumulate the total_bill in a class attribute, using something like this:

class BillsColumn(Column):
    column_total = 0

    def render(self, record):
        bills = record.certificatebills.all()
        total_bill = 0
        for bill in bills:
            total_bill += bill.bill_amount
        # accumulate
        self.column_total += total_bill
        return round(total_bill, 2)

    def render_footer(self, bound_column, table):
        return round(self.column_total, 2)

Depending on how much bills your records have, it might be more efficient to let de database do the calculation. This is called aggregation, and might look like this:

from django.db.models import Sum

class BillsColumn(Column):
    column_total = 0

    def render(self, record):
        total = record.certificatebills.aggregate(total=Sum("bill_amount"))['total']
        self.column_total += total
        return total

    def render_footer(self, bound_column, table):
        return round(self.column_total, 2)

If your table is paginated, the value in the footer only represents the bills for records in the current page. If you want to sum over all pages, you'll have to use an aggregation over all bill_amounts for all records in the table.

Jieter
  • 4,101
  • 1
  • 19
  • 31
  • Hello @jieter sorry for the late response. For some reason I got this error when using aggregation: `unsupported operand type(s) for +=: 'int' and 'NoneType' ` on the `self.column_total += total` line. But the footer is working great, exactly what I needed. Django-tables2 is awesome. Thanks for the help! Quick question: Is there a way to include the footer when exporting the table to an xlsx file? – Jordan Mora Jul 09 '18 at 14:19
  • I suspect you get the error for a record without bills? A `if total: self.column_total += total` should fix that. For the footer-export part: currently that's not possible. It should not be too hard to implement that, you are welcome to open a pull request! – Jieter Jul 09 '18 at 14:24
  • Ugh, I feel dumb for that. The `if total:` did the trick. I also added an `else: total = 0` to show a number instead of None. I'll see if I can find a way to achieve that and open a PR. Thanks again for the help! – Jordan Mora Jul 09 '18 at 14:36