django-tables2 - An app for creating HTML tables

django-tables2 turns data into HTML tables. Features:

  • Pagination
  • Ordering
  • Extendable
  • Class based view
  • Supports for queryset and list data
  • Themes

Report bugs at http://github.com/bradleyayers/django-tables2/issues

Tutorial

  1. pip install django-tables2
  2. Add 'django_tables2' to INSTALLED_APPS
  3. Add 'django.core.context_processors.request' to TEMPLATE_CONTEXT_PROCESSORS

We’re going to run through creating a tutorial app. Let’s start with a simple model:

# tutorial/models.py
class Person(models.Model):
    name = models.CharField(verbose_name="full name")

Add some data so you have something to display in the table. Now write a view to pass a Person queryset into a template:

# tutorial/views.py
from django.shortcuts import render

def people(request):
    return render(request, "people.html", {"people": Person.objects.all()})

Finally, implement the template:

{# tutorial/templates/people.html #}
{% load render_table from django_tables2 %}
<!doctype html>
<html>
    <head>
        <link rel="stylesheet" href="{{ STATIC_URL }}django_tables2/themes/paleblue/css/screen.css" />
    </head>
    <body>
        {% render_table people %}
    </body>
</html>

Hook the view up in your URLs, and load the page, you should see:

An example table rendered using django-tables2

While simple, passing a queryset directly to {% render_table %} doesn’t allow for any customisation. For that, you must define a Table class.

# tutorial/tables.py
import django_tables2 as tables
from tutorial.models import Person

class PersonTable(tables.Table):
    class Meta:
        model = Person
        # add class="paleblue" to <table> tag
        attrs = {"class": "paleblue"}

You’ll then need to instantiate and configure the table in the view, before adding it to the context.

# tutorial/views.py
from django.shortcuts import render
from django_tables2   import RequestConfig
from tutorial.models  import Person
from tutorial.tables  import PersonTable

def people(request):
    table = PersonTable(Person.objects.all())
    RequestConfig(request).configure(table)
    return render(request, 'people.html', {'table': table})

Using RequestConfig automatically pulls values from request.GET and updates the table accordingly. This enables data ordering and pagination.

Rather than passing a queryset to {% render_table %}, instead pass the table.

{% render_table table %}

Note

{% render_table %} works best when it’s used in a template that contains the current request in the context as request. The easiest way to enable this, is to ensure that the TEMPLATE_CONTEXT_PROCESSORS setting contains "django.core.context_processors.request".

At this point you haven’t actually customised anything, you’ve merely added the boilerplate code that {% render_table %} does for you when given a queryset. The remaining sections in this document describe how to change various aspects of the table.

Populating a table with data

Tables are compatible with a range of input data structures. If you’ve seen the tutorial you’ll have seen a queryset being used, however any iterable that supports len() and contains items that expose key-based accessed to column values is fine.

An an example we’ll demonstrate using list of dicts. When defining a table it’s necessary to declare each column. If your data matches the fields in a model, columns can be declared automatically for you via the Table.Meta.model option, but for non-queryset data you’ll probably want to declare them manually:

import django_tables2 as tables

data = [
    {"name": "Bradley"},
    {"name": "Stevie"},
]

class NameTable(tables.Table):
    name = tables.Column()

table = NameTable(data)

You can use this technique to override columns that were automatically created via Table.Meta.model too:

# models.py
from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=200)


# tables.py
import django_tables2 as tables
from .models import Person

class PersonTable(tables.Table):
    name = tables.Column(verbose_name="full name")

    class Meta:
        model = Person

Specifying alternative data for a column

Each column has a “key” that describes which value to pull from each record to populate the column’s cells. By default, this key is just the name given to the column, but it can be changed to allow foreign key traversal or other complex cases.

To reduce ambiguity, rather than calling it a “key”, it’s been given the special name “accessor”.

Accessors are just dotted paths that describe how an object should be traversed to reach a specific value. To demonstrate how they work we’ll use them directly:

>>> from django_tables2 import A
>>> data = {"abc": {"one": {"two": "three"}}}
>>> A("abc.one.two").resolve(data)
"three"

Dots represent a relationships, and are attempted in this order:

  1. Dictionary lookup a[b]
  2. Attribute lookup a.b
  3. List index lookup a[int(b)]

Then, if the value is callable, it is called and the result is used.

Specifying alternative ordering for a column

When using queryset data, it’s possible for a column to present a computed value that doesn’t correspond to a column in the database. In this situation attempting to order the column will cause a database exception.

Example:

# models.py
class Person(models.Model):
    first_name = models.CharField(max_length=200)
    family_name = models.CharField(max_length=200)

    @property
    def name(self):
        return u"%s %s" % (self.first_name, self.family_name)

# tables.py
class PersonTable(tables.Table):
    name = tables.Column()
>>> table = PersonTable(Person.objects.all())
>>> table.order_by = "name"
>>> table.as_html()
...
FieldError: Cannot resolve keyword u'name' into field. Choices are: first_name, family_name

The solution is to declare which fields should be used when ordering on via the order_by argument:

# tables.py
class PersonTable(tables.Table):
    name = tables.Column(order_by=("first_name", "family_name"))

Accessor syntax can be used for the values, but they must terminate on a model field.

If ordering doesn’t make sense for a particular column, it can be disabled via the orderable argument:

class SimpleTable(tables.Table):
    name = tables.Column()
    actions = tables.Column(orderable=False)

Swapping the position of columns

By default columns are positioned in the same order as they are declared, however when mixing auto-generated columns (via Table.Meta.model) with manually declared columns, the column sequence becomes ambiguous.

To resolve the ambiguity, columns sequence can be declared via the Table.Meta.sequence option:

class PersonTable(tables.Table):
    selection = tables.CheckBoxColumn(accessor="pk", orderable=False)

    class Meta:
        model = Person
        sequence = ("selection", "first_name", "last_name")

The special value "..." can be used to indicate that any omitted columns should inserted at that location. As such it can be used at most once.

Customising column headings

The header cell for each column comes from header. By default this method returns verbose_name, falling back to the titlised attribute name of the column in the table class.

When using queryset data and a verbose name hasn’t been explicitly defined for a column, the corresponding model field’s verbose name will be used.

Consider the following:

>>> class Person(models.Model):
...     first_name = models.CharField(verbose_name='model verbose name', max_length=200)
...     last_name = models.CharField(max_length=200)
...     region = models.ForeignKey('Region')
...
>>> class Region(models.Model):
...     name = models.CharField(max_length=200)
...
>>> class PersonTable(tables.Table):
...     first_name = tables.Column()
...     ln = tables.Column(accessor='last_name')
...     region_name = tables.Column(accessor='region.name')
...
>>> table = PersonTable(Person.objects.all())
>>> table.columns['first_name'].header
u'Model Verbose Name'
>>> table.columns['ln'].header
u'Last Name'
>>> table.columns['region_name'].header
u'Name'

As you can see in the last example (region name), the results are not always desirable when an accessor is used to cross relationships. To get around this be careful to define Column.verbose_name.

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.

Querystring fields

Tables pass data via the querystring to indicate ordering and pagination preferences.

The names of the querystring variables are configurable via the options:

  • order_by_field – default: "sort"
  • page_field – default: "page"
  • per_page_field – default: "per_page", note: this field currently isn’t used by {% render_table %}

Each of these can be specified in three places:

  • Table.Meta.foo
  • Table(..., foo=...)
  • Table(...).foo = ...

If you’re using multiple tables on a single page, you’ll want to prefix these fields with a table-specific name. e.g.

def people_listing(request):
    config = RequestConfig(request)
    table1 = PeopleTable(Person.objects.all(), prefix="1-")  # prefix specified
    table2 = PeopleTable(Person.objects.all(), prefix="2-")  # prefix specified
    config.configure(table1)
    config.configure(table2)
    return render(request, "people_listing.html",
                  {"table1": table1, "table2": table2})

Column attributes

Column attributes can be specified using the dict with specific keys. The dict defines HTML attributes for one of more elements within the column. Depending on the column, different elements are supported, however th, td, and cell are supported universally.

e.g.

>>> import django_tables2 as tables
>>>
>>> class SimpleTable(tables.Table):
...     name = tables.Column(attrs={"th": {"id": "foo"}})
...
>>> SimpleTable(data).as_html()
"{snip}<thead><tr><th id="foo" class="name">{snip}<tbody><tr><td class="name">{snip}"

th and td are special cases because they’re extended during rendering to add the column name as a class. This is done to make writing CSS easier. Have a look at each column’s API reference to find which elements are supported.

Built-in columns

For common use-cases the following columns are included:

Template tags

render_table

Renders a Table object to HTML and enables as many features in the output as possible.

{% load django_tables2 %}
{% render_table table %}

{# Alternatively a specific template can be used #}
{% render_table table "path/to/custom_table_template.html" %}

If the second argument (template path) is given, the template will be rendered with a RequestContext and the table will be in the variable table.

Note

This tag temporarily modifies the Table object during rendering. A context attribute is added to the table, providing columns with access to the current context for their own rendering (e.g. TemplateColumn).

This tag requires that the template in which it’s rendered contains the HttpRequest inside a request variable. This can be achieved by ensuring the TEMPLATE_CONTEXT_PROCESSORS setting contains "django.core.context_processors.request". By default it is not included, and the setting itself is not even defined within your project’s settings.py. To resolve this add the following to your settings.py:

from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS
TEMPLATE_CONTEXT_PROCESSORS += ('django.core.context_processors.request',)

querystring

A utility that allows you to update a portion of the query-string without overwriting the entire thing.

Let’s assume we have the querystring ?search=pirates&sort=name&page=5 and we want to update the sort parameter:

{% querystring "sort"="dob" %}           # ?search=pirates&sort=dob&page=5
{% querystring "sort"="" %}              # ?search=pirates&page=5
{% querystring "sort"="" "search"="" %}  # ?page=5

{% with "search" as key %}               # supports variables as keys
{% querystring key="robots" %}           # ?search=robots&page=5
{% endwith %}

This tag requires the django.core.context_processors.request context processor, see render_table.

Template filters

title

String filter that performs title case conversion on a per-word basis, leaving words containing upper-case letters alone.

{{ "start 6PM"|title }}   # Start 6PM
{{ "sTart 6pm"|title }}   # sTart 6pm

Warning

Be careful when loading the django_tables2 template library to not in advertantly load title. You should always use the {% load ... from ... %} syntax.

Class Based Generic Mixins

Django 1.3 introduced class based views as a mechanism to reduce the repetition in view code. django-tables2 comes with a single class based view mixin: SingleTableMixin. It makes it trivial to incorporate a table into a view/template.

The following view parameters are supported:

  • table_class –- the table class to use, e.g. SimpleTable
  • table_data (or get_table_data()) – the data used to populate the table
  • context_table_name – the name of template variable containing the table object
  • table_pagination – pagination options to pass to RequestConfig

For example:

from django_tables2 import SingleTableView


class Person(models.Model):
    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)


class PersonTable(tables.Table):
    class Meta:
        model = Simple


class PersonList(SingleTableView):
    model = Person
    table_class = PersonTable

The template could then be as simple as:

{% load render_table from django_tables2 %}
{% render_table table %}

Such little code is possible due to the example above taking advantage of default values and SimpleTableMixin‘s eagarness at finding data sources when one isn’t explicitly defined.

Note

If you need more than one table on a page, use SingleTableView and use get_context_data to initialise the other tables and add them to the context.

Note

You don’t have to base your view on ListView, you’re able to mix SingleTableMixin directly.

Table Mixins

It’s possible to create a mixin for a table that overrides something, however unless it itself is a subclass of Table class variable instances of Column will not be added to the class which is using the mixin.

Example:

>>> class UselessMixin(object):
...     extra = tables.Column()
...
>>> class TestTable(UselessMixin, tables.Table):
...     name = tables.Column()
...
>>> TestTable.base_columns.keys()
['name']

To have a mixin contribute a column, it needs to be a subclass of Table. With this in mind the previous example should have been written as follows:

>>> class UsefulMixin(tables.Table):
...     extra = tables.Column()
...
>>> class TestTable(UsefulMixin, tables.Table):
...     name = tables.Column()
...
>>> TestTable.base_columns.keys()
['extra', 'name']

Tables for models

If you build use tables to display QuerySet data, rather than defining each column manually in the table, the Table.Meta.model option allows tables to be dynamically created based on a model:

# models.py
class Person(models.Model):
    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)
    user = models.ForeignKey("auth.User")
    dob = models.DateField()

# tables.py
class PersonTable(tables.Table):
    class Meta:
        model = Person

This has a number of benefits:

  • Less code, easier to write, more DRY
  • Columns use the field’s verbose_name
  • Specialised columns are used where possible (e.g. DateColumn for a DateField)

When using this approach, the following options are useful:

  • sequence – reorder columns
  • fields – specify model fields to include
  • exclude – specify model fields to exclude

Controlling localization

Note

This functionality doesn’t work in Django prior to version 1.3

Django_tables2 allows you to define which column of a table should or should not be localized. For example you may want to use this feature in following use cases:

  • You want to format some columns representing for example numeric values in the given locales even if you don’t enable USE_L10N in your settings file.
  • You don’t want to format primary key values in your table even if you enabled USE_L10N in your settings file.

This control is done by using two filter functions in Django’s l10n library named localize and unlocalize. Check out Django docs about localization for more information about them.

There are two ways of controling localization in your columns.

First one is setting the localize attribute in your column definition to True or False. Like so:

class PersonTable(tables.Table):
   id = tables.Column(name="id", accessor="pk", localize=False)
   class Meta:
       model = Person

Note

The default value of the localize attribute is None which means the formatting of columns is dependant from the USE_L10N setting.

The second way is to define a localize and/or unlocalize tuples in your tables Meta class (jutst like with fields or exclude). You can do this like so:

class PersonTable(tables.Table):
   id = tables.Column(accessor="pk")
   value = tables.Column(accessor="some_numerical_field")
   class Meta:
       model = Person
       unlocalize = ('id',)
       localize = ('value',)

If you define the same column in both localize and unlocalize then the value of this column will be “unlocalized” which means that unlocalize has higher precedence.

API Reference

Accessor (A)

class django_tables2.utils.Accessor[source]

A string describing a path from one object to another via attribute/index accesses. For convenience, the class has an alias A to allow for more concise code.

Relations are separated by a . character.

RequestConfig

class django_tables2.config.RequestConfig(request, paginate=True)[source]

A configurator that uses request data to setup a table.

Parameters:paginate (dict or bool) –

indicates whether to paginate, and if so, what default values to use. If the value evaluates to False, pagination will be disabled. A dict can be used to specify default values for the call to paginate (e.g. to define a default per_page value).

A special silent item can be used to enable automatic handling of pagination exceptions using the following algorithm:

  • If PageNotAnInteger` is raised, show the first page.
  • If EmptyPage is raised, show the last page.

Table

class django_tables2.tables.Table(data, order_by=None, orderable=None, empty_text=None, exclude=None, attrs=None, sequence=None, prefix=None, order_by_field=None, page_field=None, per_page_field=None, template=None, sortable=None, default=None, request=None)
as_html()

Render the table to a simple HTML table.

If this method is used in the request/response cycle, any links generated will clobber the querystring of the request. Use the {% render_table %} template tag instead.

paginate(klass=<class 'django.core.paginator.Paginator'>, per_page=None, page=1, *args, **kwargs)

Paginates the table using a paginator and creates a page property containing information for the current page.

Parameters:
  • klass (Paginator class) – a paginator class to paginate the results
  • per_page (int) – how many records are displayed on each page
  • page (int) – which page should be displayed.

Extra arguments are passed to the paginator.

Pagination exceptions (EmptyPage and PageNotAnInteger) may be raised from this method and should be handled by the caller.

Table.Meta

class Table.Meta

Provides a way to define global settings for table, as opposed to defining them for each instance.

attrs

Allows custom HTML attributes to be specified which will be added to the <table> tag of any table rendered via Table.as_html() or the render_table template tag.

Type:dict
Default:{}

This is typically used to enable a theme for a table (which is done by adding a CSS class to the <table> element). i.e.:

class SimpleTable(tables.Table):
    name = tables.Column()

    class Meta:
        attrs = {"class": "paleblue"}

New in version 0.15.0.

It’s possible to use callables to create dynamic values. A few caveats:

  • It’s not supported for dict keys, i.e. only values.
  • All values will be resolved on table instantiation.

Consider this example where a unique id is given to each instance of the table:

import itertools
counter = itertools.count()

class UniqueIdTable(tables.Table):
    name = tables.Column()

    class Meta:
        attrs = {"id": lambda: "table_%d" % next(counter)}

Note

This functionality is also available via the attrs keyword argument to a table’s constructor.

empty_text

Defines the text to display when the table has no rows.

Type:unicode
Default:None

If the table is empty and bool(empty_text) is True, a row is displayed containing empty_text. This is allows a message such as There are currently no FOO. to be displayed.

Note

This functionality is also available via the empty_text keyword argument to a table’s constructor.

exclude

Defines which columns should be excluded from the table. This is useful in subclasses to exclude columns in a parent.

Type:tuple of unicode
Default:()

Example:

>>> class Person(tables.Table):
...     first_name = tables.Column()
...     last_name = tables.Column()
...
>>> Person.base_columns
{'first_name': <django_tables2.columns.Column object at 0x10046df10>,
'last_name': <django_tables2.columns.Column object at 0x10046d8d0>}
>>> class ForgetfulPerson(Person):
...     class Meta:
...         exclude = ("last_name", )
...
>>> ForgetfulPerson.base_columns
{'first_name': <django_tables2.columns.Column object at 0x10046df10>}

Note

This functionality is also available via the exclude keyword argument to a table’s constructor.

However, unlike some of the other Table.Meta options, providing the exclude keyword to a table’s constructor won’t override the Meta.exclude. Instead, it will be effectively be added to it. i.e. you can’t use the constructor’s exclude argument to undo an exclusion.

fields

Used in conjunction with model, specifies which fields should have columns in the table.

Type:tuple of unicode or None
Default:None

If None, all fields are used, otherwise only those named.

Example:

# models.py
class Person(models.Model):
    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)

# tables.py
class PersonTable(tables.Table):
    class Meta:
        model = Person
        fields = ("first_name", )
model

A model to inspect and automatically create corresponding columns.

Type:Django model
Default:None

This option allows a Django model to be specified to cause the table to automatically generate columns that correspond to the fields in a model.

order_by

The default ordering. e.g. ('name', '-age'). A hyphen - can be used to prefix a column name to indicate descending order.

Type:tuple
Default:()

Note

This functionality is also available via the order_by keyword argument to a table’s constructor.

sequence

The sequence of the table columns. This allows the default order of columns (the order they were defined in the Table) to be overridden.

Type:any iterable (e.g. tuple or list)
Default:()

The special item "..." can be used as a placeholder that will be replaced with all the columns that weren’t explicitly listed. This allows you to add columns to the front or back when using inheritence.

Example:

>>> class Person(tables.Table):
...     first_name = tables.Column()
...     last_name = tables.Column()
...
...     class Meta:
...         sequence = ("last_name", "...")
...
>>> Person.base_columns.keys()
['last_name', 'first_name']

The "..." item can be used at most once in the sequence value. If it’s not used, every column must be explicitly included. e.g. in the above example, sequence = ("last_name", ) would be invalid because neither "..." or "first_name" were included.

Note

This functionality is also available via the sequence keyword argument to a table’s constructor.

orderable

Default value for column’s orderable attribute.

Type:bool
Default:True

If the table and column don’t specify a value, a column’s orderable value will fallback to this. object specify. This provides an easy mechanism to disable ordering on an entire table, without adding orderable=False to each column in a table.

Note

This functionality is also available via the orderable keyword argument to a table’s constructor.

template

The default template to use when rendering the table.

Type:unicode
Default:"django_tables2/table.html"

Note

This functionality is also available via the template keyword argument to a table’s constructor.

localize

Specifies which fields should be localized in the table. Read Controlling localization for more information.

Type:tuple of unicode
Default:empty tuple
unlocalize

Specifies which fields should be unlocalized in the table. Read Controlling localization for more information.

Type:tuple of unicode
Default:empty tuple

BooleanColumn

class django_tables2.columns.BooleanColumn(null=False, yesno=u'u2714, u2718', **kwargs)

A column suitable for rendering boolean data.

Parameters:
  • null (bool) – is None different from False?
  • yesno (iterable or string) – text to display for True/False values, comma separated

Rendered values are wrapped in a <span> to allow customisation by themes. By default the span is given the class true, false.

In addition to attrs keys supported by Column, the following are available:

  • span – adds attributes to the <span> tag

Column

class django_tables2.columns.Column(verbose_name=None, accessor=None, default=None, visible=True, orderable=None, attrs=None, order_by=None, sortable=None, empty_values=None, localize=None)

Represents a single column of a table.

Column objects control the way a column (including the cells that fall within it) are rendered.

attrs

HTML attributes for elements that make up the column.

Type:dict

This API is extended by subclasses to allow arbitrary HTML attributes to be added to the output.

By default Column supports:

  • thtable/thead/th elements
  • tdtable/tbody/tr/td elements
  • cell – fallback if th or td isn’t defined
accessor

An accessor that describes how to extract values for this column from the table data.

Type:string or Accessor
default

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.

The default value may affect ordering, depending on the type of data the table is using. The only case where ordering is not affected is when a QuerySet is used as the table data (since sorting is performed by the database).

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

Allows one or more accessors to be used for ordering rather than accessor.

Type:unicode, tuple, Accessor
orderable

If False, this column will not be allowed to influence row ordering/sorting.

Type:bool
verbose_name

A human readable version of the column name.

Type:unicode
visible

If True, this column will be included in the HTML output.

Type:bool
localize

This attribute doesn’t work in Django 1.2

  • If True, cells of this column will be localized in the HTML output by the localize filter.
  • If False, cells of this column will be unlocalized in the HTML output by the unlocalize filter.
  • If None (the default), cell will be rendered as is and localization will depend on USE_L10N setting.
Type:bool

CheckBoxColumn

class django_tables2.columns.CheckBoxColumn(attrs=None, **extra)

A subclass of Column that renders as a checkbox form input.

This column allows a user to select a set of rows. The selection information can then be used to apply some operation (e.g. “delete”) onto the set of objects that correspond to the selected rows.

The value that is extracted from the table data for this column is used as the value for the checkbox, i.e. <input type="checkbox" value="..." />

This class implements some sensible defaults:

  • HTML input’s name attribute is the column name (can override via attrs argument).
  • orderable defaults to False.

Note

You’d expect that you could select multiple checkboxes in the rendered table and then do something with that. This functionality isn’t implemented. If you want something to actually happen, you’ll need to implement that yourself.

In addition to attrs keys supported by Column, the following are available:

  • input<input> elements in both <td> and <th>.
  • th__input – Replaces input attrs in header cells.
  • td__input – Replaces input attrs in body cells.

DateColumn

class django_tables2.columns.DateColumn(format=None, short=True, *args, **kwargs)

A column that renders dates in the local timezone.

Parameters:
  • format (unicode) – format string in same format as Django’s date template filter (optional)
  • short (bool) – if format is not specified, use Django’s SHORT_DATE_FORMAT setting, otherwise use DATE_FORMAT

DateTimeColumn

class django_tables2.columns.DateTimeColumn(format=None, short=True, *args, **kwargs)

A column that renders datetimes in the local timezone.

Parameters:
  • format (unicode) – format string for datetime (optional)
  • short (bool) – if format is not specifid, use Django’s SHORT_DATETIME_FORMAT, else DATETIME_FORMAT

EmailColumn

class django_tables2.columns.EmailColumn(attrs=None, *args, **kwargs)

A subclass of BaseLinkColumn that renders the cell value as a hyperlink.

It’s common to have a email value in a row hyperlinked to other page.

Parameters:attrs – a dict of HTML attributes that are added to the rendered <a href="...">...</a> tag

Example:

# models.py
class Person(models.Model):
    name = models.CharField(max_length=200)
    email =  models.EmailField()

# tables.py
class PeopleTable(tables.Table):
    name = tables.Column()
    email = tables.EmailColumn()

FileColumn

class django_tables2.columns.FileColumn(verify_exists=True, **kwargs)

Attempts to render FieldFile (or other storage backend File) as a hyperlink.

When the file is accessible via a URL, the file is rendered as a hyperlink. The basename is used as the text:

<a href="/media/path/to/receipt.pdf" title="path/to/receipt.pdf">receipt.pdf</a>

When unable to determine the URL, a span is used instead:

<span title="path/to/receipt.pdf">receipt.pdf</span>

Column.attrs keys a and span can be used to add additional attributes.

Parameters:verify_exists (bool) – attempt to determine if the file exists

If verify_exists, the HTML class exists or missing is added to the element to indicate the integrity of the storage.

LinkColumn

class django_tables2.columns.LinkColumn(viewname, urlconf=None, args=None, kwargs=None, current_app=None, attrs=None, **extra)

Renders a normal value as an internal hyperlink to another page.

It’s common to have the primary value in a row hyperlinked to the page dedicated to that record.

The first arguments are identical to that of reverse and allows an internal URL to be described. The last argument attrs allows custom HTML attributes to be added to the rendered <a href="..."> tag.

Parameters:
  • viewname – See reverse.
  • urlconf – See reverse.
  • args – See reverse. **
  • kwargs – See reverse. **
  • current_app – See reverse.
  • attrs – a dict of HTML attributes that are added to the rendered <input type="checkbox" .../> tag

** In order to create a link to a URL that relies on information in the current row, Accessor objects can be used in the args or kwargs arguments. The accessor will be resolved using the row’s record before reverse is called.

Example:

# models.py
class Person(models.Model):
    name = models.CharField(max_length=200)

# urls.py
urlpatterns = patterns('',
    url('people/(\d+)/', views.people_detail, name='people_detail')
)

# tables.py
from django_tables2.utils import A  # alias for Accessor

class PeopleTable(tables.Table):
    name = tables.LinkColumn('people_detail', args=[A('pk')])

In addition to attrs keys supported by Column, the following are available:

  • a<a> elements in <td>.

TemplateColumn

class django_tables2.columns.TemplateColumn(template_code=None, template_name=None, **extra)

A subclass of Column that renders some template code to use as the cell value.

Parameters:
  • template_code (unicode) – the template code to render
  • template_name (unicode) – the name of the template to render

A Template object is created from the template_code or template_name and rendered with a context containing:

  • record – data record for the current row
  • value – value from record that corresponds to the current column
  • default – appropriate default value to use as fallback

Example:

class ExampleTable(tables.Table):
    foo = tables.TemplateColumn('{{ record.bar }}')
    # contents of `myapp/bar_column.html` is `{{ value }}`
    bar = tables.TemplateColumn(template_name='myapp/name2_column.html')

Both columns will have the same output.

Important

In order to use template tags or filters that require a RequestContext, the table must be rendered via {% render_table %}.

URLColumn

class django_tables2.columns.URLColumn(attrs=None, *args, **kwargs)

Renders URL values as hyperlinks.

Example:

>>> class CompaniesTable(tables.Table):
...     www = tables.URLColumn()
...
>>> table = CompaniesTable([{"www": "http://google.com"}])
>>> table.rows[0]["www"]
u'<a href="http://google.com">http://google.com</a>'

Additional attributes for the <a> tag can be specified via attrs['a'].

See Internal APIs for internal classes.

Upgrading from django-tables Version 1

  • Change your INSTALLLED_APPS entry from "django_tables.app" to "django_tables2".

  • Change all your import references from django_tables to django_tables2.

  • Replace all references to the old MemoryTable and ModelTable classes with simply Table.

  • In your templates, load the django_tables2 template library; {% load django_tables2 %} instead of {% load tables %}.

  • A table object is no longer iterable; rather than for row in table, instead you now do explicitly: for row in table.rows.

  • If you were using row.data to access a row’s underlying data, replace it with row.record instead.

  • When declaring columns, replace the use of:

    name_in_dataset = tables.Column(name="wanted_column_name")
    

    with:

    wanted_column_name = tables.Column(accessor="name_in_dataset")
    
  • When declaring columns, replace the use of:

    column_to_override = tables.Column(name="wanted_column_name", data="name_in_dataset")
    

    with:

    wanted_column_name = tables.Column(accessor="name_in_dataset")
    

    and exclude column_to_override via the table meta data.

  • When generating the link to order the column, instead of:

    {% set_url_param sort=column.name_toggled %}
    

    use:

    {% querystring table.order_by_field=column.order_by_alias.next %}
    
  • Replace:

    {{ column.is_ordered_reverse }} and {{ column.is_ordered_straight }}
    

    with:

    {{ column.order_by.is_descending }} and {{ column.order_by.is_ascending }}
    

Glossary

accessor
Refers to an Accessor object
column name

The name given to a column. In the follow example, the column name is age.

class SimpleTable(tables.Table):
    age = tables.Column()
empty value
An empty value is synonymous with “no value”. Columns have an empty_values attribute that contains values that are considered empty. It’s a way to declare which values from the database correspond to null/blank/missing etc.
order by alias

A prefixed column name that describes how a column should impact the order of data within the table. This allows the implementation of how a column affects ordering to be abstracted, which is useful (e.g. in querystrings).

class ExampleTable(tables.Table):
    name = tables.Column(order_by=('first_name', 'last_name'))

In this example -name and name are valid order by aliases. In a querystring you might then have ?order=-name.

table
The traditional concept of a table. i.e. a grid of rows and columns containing data.
view
A Django view.
record
A single Python object used as the data for a single row.
render
The act of serialising a Table into HTML.
template
A Django template.
table data
An interable of records that Table uses to populate its rows.