Customizing headers and footers¶
By default an header and no footer will be rendered.
Adding column headers¶
The header cell for each column comes from header
. By default this
method returns verbose_name
, falling back to the capitalized attribute
name of the column in the table class.
When using QuerySet data and a verbose name has not been explicitly defined for
a column, the corresponding model field’s verbose_name
will be used.
Consider the following:
>>> class Region(models.Model):
... name = models.CharField(max_length=200)
...
>>> 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 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
'Model Verbose Name'
>>> table.columns["ln"].header
'Last Name'
>>> table.columns["region_name"].header
'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
.
Changing class names for ordered column headers¶
When a column is ordered in an ascending state there needs to be a way to show
it in the interface. django-tables2 does this by adding an asc
class for
ascending or a desc
class for descending. It should also be known that any
orderable column is added with an orderable
class to the column header.
Sometimes there may be a need to change these default classes.
On the attrs
attribute of the table, you can add a th
key with the value of
a dictionary. Within that th
dictionary, you may add an _ordering
key also
with the value of a dictionary.
The _ordering
element is optional and all elements within it are optional.
Inside you can have an orderable
element, which will change the default
orderable
class name. You can also have ascending
which will will change the
default asc
class name. And lastly, you can have descending
which will
change the default desc
class name.
Example:
class Table(tables.Table):
Meta:
attrs = {
"th" : {
"_ordering": {
"orderable": "sortable", # Instead of `orderable`
"ascending": "ascend", # Instead of `asc`
"descending": "descend" # Instead of `desc`
}
}
}
It can also be specified at initialization using the attrs
for both: table and
column:
ATTRIBUTES = {
"th" : {
"_ordering": {
"orderable": "sortable", # Instead of `orderable`
"ascending": "ascend", # Instead of `asc`
"descending": "descend" # Instead of `desc`
}
}
}
table = tables.Table(queryset, attrs=ATTRIBUTES)
# or
class Table(tables.Table):
my_column = tables.Column(attrs=ATTRIBUTES)
Adding column footers¶
By default, no footer will be rendered. If you want to add a footer, define a footer on at least one column.
That will make the table render a footer on every view of the table. It is up to you to decide if that makes sense if your table is paginated.
Pass footer
-argument to the Column
constructor.¶
The simplest case is just passing a str
as the footer argument to a column:
country = tables.Column(footer="Total:")
This will just render the string in the footer. If you need to do more complex things, like showing a sum or an average, you can pass a callable:
population = tables.Column(
footer=lambda table: sum(x["population"] for x in table.data)
)
You can expect table
, column
and bound_column
as argument.
Define render_footer
on a custom column.¶
If you need the same footer in multiple columns, you can create your own custom column. For example this column that renders the sum of the values in the column:
class SummingColumn(tables.Column):
def render_footer(self, bound_column, table):
return sum(bound_column.accessor.resolve(row) for row in table.data)
Then use this column like so:
class Table(tables.Table):
name = tables.Column()
country = tables.Column(footer="Total:")
population = SummingColumn()
Note
If you are summing over tables with big datasets, chances are it is going to be slow. You should use some database aggregation function instead.