Custom rendering

Various options are available for changing the way the table is rendered. Each approach has a different balance of ease-of-use and flexibility.

Table.render_FOO() methods

To change how a column is rendered, implement a render_FOO method on the table (where FOO is the column name). This approach is suitable if you have a one-off change that you don’t want to use in multiple tables.

Supported keyword arguments include:

  • record – the entire record for the row from the table data
  • value – the value for the cell retrieved from the table data
  • column – the Column object
  • bound_column – the BoundColumn object
  • bound_row – the BoundRow object
  • table – alias for self

Here’s an example where the first column displays the current row number:

>>> import django_tables2 as tables
>>> import itertools
>>> class SimpleTable(tables.Table):
...     row_number = tables.Column(empty_values=())
...     id = tables.Column()
...     age = tables.Column()
...
...     def __init__(self, *args, **kwargs):
...         super(SimpleTable, self).__init__(*args, **kwargs)
...         self.counter = itertools.count()
...
...     def render_row_number(self):
...         return 'Row %d' % next(self.counter)
...
...     def render_id(self, value):
...         return '<%s>' % value
...
>>> table = SimpleTable([{'age': 31, 'id': 10}, {'age': 34, 'id': 11}])
>>> for cell in table.rows[0]:
...     print cell
...
Row 0
<10>
31

Python’s inspect.getargspec is used to only pass the arguments declared by the function. This means it’s not necessary to add a catch all (**) keyword argument.

Important

render methods are only called if the value for a cell is determined to be not an empty value. When a value is in Column.empty_values, a default value is rendered instead (both Column.render and Table.render_FOO are skipped).

Subclassing Column

Defining a column subclass allows functionality to be reused across tables. Columns have a render method that behaves the same as Table.render_FOO() methods methods on tables:

>>> import django_tables2 as tables
>>>
>>> class UpperColumn(tables.Column):
...     def render(self, value):
...         return value.upper()
...
>>> class Example(tables.Table):
...     normal = tables.Column()
...     upper = UpperColumn()
...
>>> data = [{'normal': 'Hi there!',
...          'upper':  'Hi there!'}]
...
>>> table = Example(data)
>>> # renders to something like this:
'''<table>
    <thead><tr><th>Normal</th><th>Upper</th></tr></thead>
    <tbody><tr><td>Hi there!</td><td>HI THERE!</td></tr></tbody>
</table>'''

See Table.render_FOO() methods for a list of arguments that can be accepted.

For complicated columns, you may want to return HTML from the render() method. Make sure to use Django’s html formatting functions:

>>> from django.utils.html import format_html
>>>
>>> class ImageColumn(tables.Column):
...     def render(self, value):
...         return format_html('<img src="/media/img/{}.jpg" />', value)
...

CSS

In order to use CSS to style a table, you’ll probably want to add a class or id attribute to the <table> element. django-tables2 has a hook that allows arbitrary attributes to be added to the <table> tag.

>>> import django_tables2 as tables
>>>
>>> class SimpleTable(tables.Table):
...     id = tables.Column()
...     age = tables.Column()
...
...     class Meta:
...         attrs = {'class': 'mytable'}
...
>>> table = SimpleTable()
>>> # renders to something like this:
'<table class="mytable">...'

Custom Template

And of course if you want full control over the way the table is rendered, ignore the built-in generation tools, and instead pass an instance of your Table subclass into your own template, and render it yourself.

Have a look at the django_tables2/table.html template for an example.

Table Of Contents

This Page