Custom rendering — django-tables2 1.0.6 documentation

# 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)
    >>> table.as_html()
    u'<table><thead><tr><th>Normal</th><th>Upper</th></tr></thead><tbody><tr><td>Hi there!</td><td>HI THERE!</td></tr></tbody></table>\n'

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. This is fine, but be sure to mark the string as safe to avoid it being escaped:

    >>> from django.utils.safestring import mark_safe
    >>> from django.utils.html import escape
    >>>
    >>> class ImageColumn(tables.Column):
    ...     def render(self, value):
    ...         return mark_safe('<img src="/media/img/%s.jpg" />'
    ...                          % escape(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 abitrary 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()
    >>> table.as_html()
    '<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.