File: custom-rendering.rst

package info (click to toggle)
django-tables 1.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 916 kB
  • ctags: 1,223
  • sloc: python: 3,859; makefile: 120
file content (142 lines) | stat: -rw-r--r-- 4,447 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
.. _custom-rendering:

Custom rendering
================

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


.. _table.render_foo:

:meth:`Table.render_FOO` methods
--------------------------------

To change how a column is rendered, implement a ``render_FOO`` method on the
table (where ``FOO`` is the :term:`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 :term:`table data`
- ``value`` -- the value for the cell retrieved from the :term:`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 :term:`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:

Subclassing `.Column`
---------------------

Defining a column subclass allows functionality to be reused across tables.
Columns have a `render` method that behaves the same as :ref:`table.render_foo`
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 :ref:`table.render_foo` for a list of arguments that can be accepted.

For complicated columns, you may want to return HTML from the
:meth:`~Column.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:

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.

.. sourcecode:: python

    >>> 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:

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.