How to add counter column in django-tables2?

Other answers all have the itertools.count instance in the toplevel scope of the tables.py file. This makes the counter persist between page loads, it will only be reset when the server is restarted. A better solution is to add the counter as instance variable on the table like this:

import django_tables2 as tables
import itertools

class CountryTable(tables.Table):
    counter = tables.Column(empty_values=(), orderable=False)

    def render_counter(self):
        self.row_counter = getattr(self, 'row_counter', itertools.count())
        return next(self.row_counter)

This will make sure the counter is reset every time the table is instantiated.


From the documentation of Column

default (str or callable):

The default value for the column. This can be a value or a callable object [1]. If an object in the data provides None for a column, the default will be used instead.

[1] - The provided callable object must not expect to receive any arguments.

What you are passing next(counter) you are passing the result of a function which seems to be an integer.

You can either define a function:

def next_count():
    return next(counter)

and, use it as default:

priority = tables.Column(verbose_name="#", default=next_count)

Or, you can use the lambda function as mentioned in @Sayse's comments:

priority = tables.Column(verbose_name="#", default=lambda: next(counter))

Building on Jieter's answer, you can handle pagination with this minor modification:

import django_tables2 as tables
import itertools

class CountryTable(tables.Table):
    counter = tables.Column(empty_values=(), orderable=False)

    def render_counter(self):
        self.row_counter = getattr(self, 'row_counter',
                                   itertools.count(self.page.start_index()))
        return next(self.row_counter)

The row numbering will be globally correct even in pages after the first. Note that the index is 1-based in this case.