7d5d33ace068b424d0608fef40564c4ac3028d7a
[django-tables2.git] / docs / index.rst
1 .. default-domain:: py
2
3 ================================================
4 django-tables2 - An app for creating HTML tables
5 ================================================
6
7 django-tables2 simplifies the task of turning sets of datainto HTML tables. It
8 has native support for pagination and sorting. It does for HTML tables what
9 ``django.forms`` does for HTML forms.
10
11 Quick start guide
12 =================
13
14 1. Download and install from https://github.com/bradleyayers/django-tables2.
15    Grab a ``.tar.gz`` of the latest tag, and run ``pip install <tar.gz>``.
16 2. Hook the app into your Django project by adding ``'django_tables2'`` to your
17    ``INSTALLED_APPS`` setting.
18 3. Write a subclass of :class:`~django_tables2.tables.Table` that describes the
19    structure of your table.
20 4. Create an instance of your table in a :term:`view`, provide it with
21    :term:`table data`, and pass it to a :term:`template` for display.
22 5. Use ``{{ table.as_html }}``, the
23    :ref:`template tag <template-tags.render_table>`, or your own
24    :ref:`custom template <custom-template>` to display the table.
25
26
27 Slow start guide
28 ================
29
30 We're going to take some data that describes three countries and
31 turn it into an HTML table. This is the data we'll be using:
32
33 .. code-block:: python
34
35     countries = [
36         {'name': 'Australia', 'population': 21, 'tz': 'UTC +10', 'visits': 1},
37         {'name': 'Germany', 'population': 81, 'tz': 'UTC +1', 'visits': 2},
38         {'name': 'Mexico', 'population': 107, 'tz': 'UTC -6', 'visits': 0},
39     ]
40
41
42 The first step is to subclass :class:`~django_tables2.tables.Table` and describe
43 the table structure. This is done by creating a column for each attribute in
44 the :term:`table data`.
45
46 .. code-block:: python
47
48     import django_tables2 as tables
49
50     class CountryTable(tables.Table):
51         name = tables.Column()
52         population = tables.Column()
53         tz = tables.Column(verbose_name='Time Zone')
54         visits = tables.Column()
55
56
57 Now that we've defined our table, it's ready for use. We simply create an
58 instance of it, and pass in our table data.
59
60 .. code-block:: python
61
62     table = CountryTable(countries)
63
64 Now we add it to our template context and render it to HTML. Typically you'd
65 write a view that would look something like:
66
67 .. code-block:: python
68
69     def home(request):
70         table = CountryTable(countries)
71         return render_to_response('home.html', {'table': table},
72                                   context_instance=RequestContext(request))
73
74 In your template, the easiest way to :term:`render` the table is via the
75 :meth:`~django_tables2.tables.Table.as_html` method:
76
77 .. code-block:: django
78
79     {{ table.as_html }}
80
81 …which will render something like:
82
83 +--------------+------------+-----------+--------+
84 | Country Name | Population | Time Zone | Visit  |
85 +==============+============+===========+========+
86 | Australia    | 21         | UTC +10   | 1      |
87 +--------------+------------+-----------+--------+
88 | Germany      | 81         | UTC +1    | 2      |
89 +--------------+------------+-----------+--------+
90 | Mexico       | 107        | UTC -6    | 0      |
91 +--------------+------------+-----------+--------+
92
93 This approach is easy, but it's not fully featured (e.g. no pagination, no
94 sorting). Don't worry it's very easy to add these. First, you must render the
95 table via the :ref:`template tag <template-tags.render_table>` rather than
96 ``as_html()``:
97
98 .. code-block:: django
99
100     {% load django_tables2 %}
101     {% render_table table %}
102
103 .. note::
104
105     ``{% render_table %}`` requires that the ``TEMPLATE_CONTEXT_PROCESSORS``
106     setting contains ``"django.core.context_processors.request"``. See
107     :ref:`template-tags.render_table` for details.
108
109 This is all that's required for the template, but in the view you'll need to
110 tell the table to which column to order by, and which page of data to display
111 (pagination). This is achieved as follows:
112
113 .. code-block:: python
114
115     def home(request):
116         countries = Country.objects.all()
117         table = CountryTable(countries, order_by=request.GET.get('sort'))
118         table.paginate(page=request.GET.get('page', 1))
119         return render_to_response('home.html', {'table': table},
120                                   context_instance=RequestContext(request))
121
122 See :ref:`ordering`, and :ref:`pagination` for more information.
123
124 The table will be rendered, but chances are it will still look quite ugly. An
125 easy way to make it pretty is to use the built-in *paleblue* theme. For this to
126 work, you must add a CSS class to the ``<table>`` tag. This can be achieved by
127 adding a ``class Meta:`` to the table class and defining a ``attrs`` variable.
128
129 .. code-block:: python
130
131     import django_tables2 as tables
132
133     class CountryTable(tables.Table):
134         name = tables.Column()
135         population = tables.Column()
136         tz = tables.Column(verbose_name='Time Zone')
137         visits = tables.Column()
138
139         class Meta:
140             attrs = {'class': 'paleblue'}
141
142 The last thing to do is to include the stylesheet in the template.
143
144 .. code-block:: html
145
146     <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}django_tables2/themes/paleblue/css/screen.css" />
147
148 Save your template and reload the page in your browser.
149
150
151 .. _table-data:
152
153 Table data
154 ==========
155
156 The data used to populate a table is called :term:`table data`. To provide a
157 table with data, pass it in as the first argument when instantiating a table.
158
159 .. code-block:: python
160
161     table = CountryTable(countries)              # valid
162     table = CountryTable(Country.objects.all())  # also valid
163
164 Each item in the :term:`table data` is called a :term:`record` and is used to
165 populate a single row in the table. By default, the table uses column names
166 as :term:`accessors <accessor>` to retrieve individual cell values. This can
167 be changed via the :attr:`~django_tables2.columns.Column.accessor` argument.
168
169 Any iterable can be used as table data, and there's builtin support for
170 :class:`QuerySet` objects (to ensure they're handled effeciently).
171
172
173 .. _ordering:
174
175 Ordering
176 ========
177
178 .. note::
179
180     If you want to change the order in which columns are displayed, see
181     :attr:`Table.Meta.sequence`. Alternatively if you're interested in the
182     order of records within the table, read on.
183
184 Changing the way records in a table are ordered is easy and can be controlled
185 via the :attr:`.Table.Meta.order_by` option. The following examples all achieve
186 the same thing:
187
188 .. code-block:: python
189
190     class SimpleTable(tables.Table):
191         name = tables.Column()
192
193         class Meta:
194             order_by = 'name'
195
196 By passing in a value for ``order_by`` into the ``Table`` constructor, the
197 ``Meta.order_by`` option can be overridden on a per-instance basis.
198
199 .. code-block:: python
200
201     class SimpleTable(tables.Table):
202         name = tables.Column()
203
204     table = SimpleTable(..., order_by='name')
205
206 This approach allows column sorting to be enabled for use with the ``{%
207 render_table %}`` template tag. The template tag converts column headers into
208 hyperlinks that add the querystring parameter ``sort`` to the current URL. This
209 means your view will need to look something like:
210
211 .. code-block:: python
212
213     def home(request):
214         countries = Country.objects.all()
215         table = CountryTable(countries, order_by=request.GET.get('sort'))
216         return render_to_response('home.html', {'table': table},
217                                   context_instance=RequestContext(request))
218
219 The final approach allows both of the previous approaches to be overridden. The
220 instance property ``order_by`` can be
221
222 .. code-block:: python
223
224     class SimpleTable(tables.Table):
225         name = tables.Column()
226
227     table = SimpleTable(...)
228     table.order_by = 'name'
229
230 ----
231
232 By default all table columns support sorting. This means that if you're using
233 the :ref:`template tag <template-tags.render_table>` to render the table,
234 users can sort the table based on any column by clicking the corresponding
235 header link.
236
237 In some cases this may not be appropriate. For example you may have a column
238 which displays data that isn't in the dataset:
239
240 .. code-block:: python
241
242     class SimpleTable(tables.Table):
243         name = tables.Column()
244         lucky_rating = tables.Column()
245
246         class Meta:
247             sortable = False
248
249         def render_lucky_rating(self):
250             import random
251             return random.randint(1, 10)
252
253 In these types of scenarios, it's simply not possible to sort the table based
254 on column data that isn't in the dataset. The solution is to disable sorting
255 for these columns.
256
257 Sorting can be disabled on a column, table, or table instance basis via the
258 :attr:`.Table.Meta.sortable` option.
259
260 To disable sorting by default for all columns:
261
262 .. code-block:: python
263
264     class SimpleTable(tables.Table):
265         name = tables.Column()
266
267         class Meta:
268             sortable = False
269
270 To disable sorting for a specific table instance:
271
272 .. code-block:: python
273
274     class SimpleTable(tables.Table):
275         name = tables.Column()
276
277     table = SimpleTable(..., sortable=False)
278     # or
279     table.sortable = False
280
281
282 .. _column-headers:
283
284 Column headers
285 ==============
286
287 The header cell for each column comes from the column's
288 :meth:`~django_tables2.columns.BoundColumn.header` method. By default this
289 method returns the column's ``verbose_name``, which is either explicitly
290 specified, or generated automatically based on the column name.
291
292 When using queryset input data, rather than falling back to the column name if
293 a ``verbose_name`` has not been specified explicitly, the queryset model's
294 field ``verbose_name`` is used.
295
296 Consider the following:
297
298     >>> class Person(models.Model):
299     ...     first_name = models.CharField(verbose_name='FIRST name', max_length=200)
300     ...     last_name = models.CharField(max_length=200)
301     ...     region = models.ForeignKey('Region')
302     ...
303     >>> class Region(models.Model):
304     ...     name = models.CharField(max_length=200)
305     ...
306     >>> class PersonTable(tables.Table):
307     ...     first_name = tables.Column()
308     ...     ln = tables.Column(accessor='last_name')
309     ...     region_name = tables.Column(accessor='region.name')
310     ...
311     >>> table = PersonTable(Person.objects.all())
312     >>> table.columns['first_name'].verbose_name
313     u'FIRST name'
314     >>> table.columns['ln'].verbose_name
315     u'Last name'
316     >>> table.columns['region_name'].verbose_name
317     u'Name'
318
319 As you can see in the last example, the results are not always desirable when
320 an accessor is used to cross relationships. To get around this be careful to
321 define a ``verbose_name`` on such columns.
322
323
324 .. _pagination:
325
326 Pagination
327 ==========
328
329 Pagination is easy, just call :meth:`.Table.paginate` and pass in the current
330 page number, e.g.
331
332 .. code-block:: python
333
334     def people_listing(request):
335         table = PeopleTable(Person.objects.all())
336         table.paginate(page=request.GET.get('page', 1))
337         return render_to_response('people_listing.html', {'table': table},
338                                   context_instance=RequestContext(request))
339
340 The last set is to render the table. :meth:`.Table.as_html` doesn't support
341 pagination, so you must use :ref:`{% render_table %}
342 <template-tags.render_table>`.
343
344 .. _custom-rendering:
345
346 Custom rendering
347 ================
348
349 Various options are available for changing the way the table is :term:`rendered
350 <render>`. Each approach has a different balance of ease-of-use and
351 flexibility.
352
353 CSS
354 ---
355
356 In order to use CSS to style a table, you'll probably want to add a
357 ``class`` or ``id`` attribute to the ``<table>`` element. ``django-tables2`` has
358 a hook that allows abitrary attributes to be added to the ``<table>`` tag.
359
360 .. code-block:: python
361
362     >>> import django_tables2 as tables
363     >>> class SimpleTable(tables.Table):
364     ...     id = tables.Column()
365     ...     age = tables.Column()
366     ...
367     ...     class Meta:
368     ...         attrs = {'class': 'mytable'}
369     ...
370     >>> table = SimpleTable()
371     >>> table.as_html()
372     '<table class="mytable">...'
373
374
375 .. _table.render_foo:
376
377 :meth:`Table.render_FOO` Methods
378 --------------------------------
379
380 If you want to adjust the way table cells in a particular column are rendered,
381 you can implement a ``render_FOO`` method. ``FOO`` is replaced with the
382 :term:`name <column name>` of the column.
383
384 This approach provides a lot of control, but is only suitable if you intend to
385 customise the rendering for a single table (otherwise you'll end up having to
386 copy & paste the method to every table you want to modify â€“ which violates
387 DRY).
388
389 For convenience, a bunch of commonly used/useful values are passed to
390 ``render_FOO`` functions, when writing the signature, simply accept the
391 arguments you're interested in, and the function will recieve them
392
393 .. note:: Due to the implementation, a "catch-extra" arguments (e.g. ``*args``
394     or ``**kwargs``) will not recieve any arguments. This is because
395     ``inspect.getargsspec()`` is used to check what arguments a ``render_FOO``
396     method expect, and only to supply those.
397
398 :param value: the value for the cell retrieved from the :term:`table data`
399 :param record: the entire record for the row from :term:`table data`
400 :param column: the :class:`.Column` object
401 :param bound_column: the :class:`.BoundColumn` object
402 :param bound_row: the :class:`.BoundRow` object
403 :param table: alias for ``self``
404
405 .. code-block:: python
406
407     >>> import django_tables2 as tables
408     >>> class SimpleTable(tables.Table):
409     ...     row_number = tables.Column()
410     ...     id = tables.Column()
411     ...     age = tables.Column()
412     ...
413     ...     def render_row_number(self):
414     ...         value = getattr(self, '_counter', 0)
415     ...         self._counter = value + 1
416     ...         return 'Row %d' % value
417     ...
418     ...     def render_id(self, value):
419     ...         return '<%s>' % value
420     ...
421     >>> table = SimpleTable([{'age': 31, 'id': 10}, {'age': 34, 'id': 11}])
422     >>> for cell in table.rows[0]:
423     ...     print cell
424     ...
425     Row 0
426     <10>
427     31
428
429
430 .. _subclassing-column:
431
432 Subclassing :class:`Column`
433 ---------------------------
434
435 If you want to have a column behave the same way in many tables, it's best to
436 create a subclass of :class:`Column` and use that when defining the table.
437
438 To change the way cells are rendered, simply override the
439 :meth:`~Column.render` method.
440
441 .. code-block:: python
442
443     >>> import django_tables2 as tables
444     >>>
445     >>> class AngryColumn(tables.Column):
446     ...     def render(self, value):
447     ...         return value.upper()
448     ...
449     >>> class Example(tables.Table):
450     ...     normal = tables.Column()
451     ...     angry = AngryColumn()
452     ...
453     >>> data = [{
454     ...     'normal': 'May I have some food?',
455     ...     'angry': 'Give me the food now!',
456     ... }, {
457     ...     'normal': 'Hello!',
458     ...     'angry': 'What are you looking at?',
459     ... }]
460     ...
461     >>> table = Example(data)
462     >>> table.as_html()
463     u'<table><thead><tr><th>Normal</th><th>Angry</th></tr></thead><tbody><tr><td>May I have some food?</td><td>GIVE ME THE FOOD NOW!</td></tr><tr><td>Hello!</td><td>WHAT ARE YOU LOOKING AT?</td></tr></tbody></table>\n'
464
465 See :ref:`table.render_foo` for a list of arguments that can be accepted.
466
467 Which, when displayed in a browser, would look something like this:
468
469 +-----------------------+--------------------------+
470 | Normal                | Angry                    |
471 +=======================+==========================+
472 | May I have some food? | GIVE ME THE FOOD NOW!    |
473 +-----------------------+--------------------------+
474 | Hello!                | WHAT ARE YOU LOOKING AT? |
475 +-----------------------+--------------------------+
476
477
478 For complicated columns, it's sometimes necessary to return HTML from a :meth:`~Column.render` method, but the string
479 must be marked as safe (otherwise it will be escaped when the table is
480 rendered). This can be achieved by using the :func:`mark_safe` function.
481
482 .. code-block:: python
483
484     >>> from django.utils.safestring import mark_safe
485     >>>
486     >>> class ImageColumn(tables.Column):
487     ...     def render(self, value):
488     ...         return mark_safe('<img src="/media/img/%s.jpg" />' % value)
489     ...
490
491
492 .. _custom-template:
493
494 Custom Template
495 ---------------
496
497 And of course if you want full control over the way the table is rendered,
498 ignore the built-in generation tools, and instead pass an instance of your
499 :class:`Table` subclass into your own template, and render it yourself:
500
501 .. code-block:: django
502
503     {% load django_tables2 %}
504     <table>
505         <thead>
506             <tr>
507             {% for column in table.columns %}
508                 <th><a href="{% set_url_param sort=column.name_toggled %}">{{ column }}</a></th>
509             {% endfor %}
510             </tr>
511         </thead>
512         <tbody>
513             {% for row in table.rows %}
514             <tr>
515                 {% for cell in row %}
516                 <td>{{ cell }}</td>
517                 {% endfor %}
518             </tr>
519             {% empty %}
520                 {% if table.empty_text %}
521                 <tr><td colspan="{{ table.columns|length }}">{{ table.empty_text }}</td></tr>
522                 {% endif %}
523             {% endfor %}
524         </tbody>
525     </table>
526
527
528 .. _template_tags:
529
530 Template tags
531 =============
532
533 .. _template-tags.render_table:
534
535 render_table
536 ------------
537
538 Renders a :class:`~django_tables2.tables.Table` object to HTML and includes as
539 many features as possible.
540
541 Sample usage:
542
543 .. code-block:: django
544
545     {% load django_tables2 %}
546     {% render_table table %}
547
548 This tag temporarily modifies the :class:`.Table` object while it is being
549 rendered. It adds a ``request`` attribute to the table, which allows
550 :class:`Column` objects to have access to a ``RequestContext``. See
551 :class:`.TemplateColumn` for an example.
552
553 This tag requires that the template in which it's rendered contains the
554 ``HttpRequest`` inside a ``request`` variable. This can be achieved by ensuring
555 the ``TEMPLATE_CONTEXT_PROCESSORS`` setting contains
556 ``"django.core.context_processors.request"``. By default it is not included,
557 and the setting itself is not even defined within your project's
558 ``settings.py``. To resolve this simply add the following to your
559 ``settings.py``:
560
561 .. code-block:: python
562
563     TEMPLATE_CONTEXT_PROCESSORS = (
564         "django.contrib.auth.context_processors.auth",
565         "django.core.context_processors.debug",
566         "django.core.context_processors.i18n",
567         "django.core.context_processors.media",
568         "django.core.context_processors.static",
569         "django.contrib.messages.context_processors.messages",
570         "django.core.context_processors.request",
571     )
572
573
574 .. _template-tags.set_url_param:
575
576 set_url_param
577 -------------
578
579 This template tag is a utility that allows you to update a portion of the
580 query-string without overwriting the entire thing. However you shouldn't need
581 to use this template tag unless you are rendering the table from scratch (i.e.
582 not using ``as_html()`` or ``{% render_table %}``).
583
584 This is very useful if you want the give your users the ability to interact
585 with your table (e.g. change the ordering), because you will need to create
586 urls with the appropriate queries.
587
588 Let's assume we have the querystring ``?search=pirates&sort=name&page=5`` and
589 we want to update the ``sort`` parameter:
590
591 .. code-block:: django
592
593     {% set_url_param sort="dob" %}         # ?search=pirates&sort=dob&page=5
594     {% set_url_param sort="" %}            # ?search=pirates&page=5
595     {% set_url_param sort="" search="" %}  # ?page=5
596
597
598
599 A table instance bound to data has two attributes ``columns`` and ``rows``,
600 which can be iterated over:
601
602 .. code-block:: django
603
604     <table>
605         <thead>
606             <tr>
607             {% for column in table.columns %}
608                 <th><a href="?sort={{ column.name_toggled }}">{{ column }}</a></th>
609             {% endfor %}
610             </tr>
611         </thead>
612         <tbody>
613         {% for row in table.rows %}
614             <tr>
615             {% for value in row %}
616                 <td>{{ value }}</td>
617             {% endfor %}
618             </tr>
619         {% endfor %}
620         </tbody>
621     </table>
622
623
624 Class Based Generic Mixins
625 ==========================
626
627 Django 1.3 introduced `class based views`__ as a mechanism to reduce the
628 repetition in view code. django-tables2 comes with a single class based view
629 mixin: ``SingleTableMixin``. It makes it trivial to incorporate a table into a
630 view/template, however it requires a few variables to be defined on the view:
631
632 - ``table_class`` â€“- the table class to use, e.g. ``SimpleTable``
633 - ``table_data`` (or ``get_table_data()``) -- the data used to populate the
634   table
635 - ``context_table_name`` -- the name of template variable containing the table
636   object
637
638 .. __: https://docs.djangoproject.com/en/1.3/topics/class-based-views/
639
640 For example:
641
642 .. code-block:: python
643
644     from django_tables2.views import SingleTableMixin
645     from django.generic.views.list import ListView
646
647
648     class Simple(models.Model):
649         first_name = models.CharField(max_length=200)
650         last_name = models.CharField(max_length=200)
651
652
653     class SimpleTable(tables.Table):
654         first_name = tables.Column()
655         last_name = tables.Column()
656
657
658     class MyTableView(SingleTableMixin, ListView):
659         model = Simple
660         table_class = SimpleTable
661
662
663 The template could then be as simple as:
664
665 .. code-block:: django
666
667     {% load django_tables2 %}
668     {% render_table table %}
669
670 Such little code is possible due to the example above taking advantage of
671 default values and ``SimpleTableMixin``'s eagarness at finding data sources
672 when one isn't explicitly defined.
673
674 .. note::
675
676     If you want more than one table on a page, at the moment the simplest way
677     to do it is to use ``SimpleTableMixin`` for one table, and write the
678     boilerplate for the other yourself in ``get_context_data()``. Obviously
679     this isn't particularly elegant, and as such will hopefully be resolved in
680     the future.
681
682
683 Table Mixins
684 ============
685
686 It's possible to create a mixin for a table that overrides something, however
687 unless it itself is a subclass of :class:`.Table` class
688 variable instances of :class:`.Column` will **not** be added to the class which is using the mixin.
689
690 Example::
691
692     >>> class UselessMixin(object):
693     ...     extra = tables.Column()
694     ...
695     >>> class TestTable(UselessMixin, tables.Table):
696     ...     name = tables.Column()
697     ...
698     >>> TestTable.base_columns.keys()
699     ['name']
700
701 To have a mixin contribute a column, it needs to be a subclass of
702 :class:`~django_tables2.tables.Table`. With this in mind the previous example
703 *should* have been written as follows::
704
705     >>> class UsefulMixin(tables.Table):
706     ...     extra = tables.Column()
707     ...
708     >>> class TestTable(UsefulMixin, tables.Table):
709     ...     name = tables.Column()
710     ...
711     >>> TestTable.base_columns.keys()
712     ['extra', 'name']
713
714
715 Tables for models
716 =================
717
718 Most of the time you'll probably be making tables to display queryset data, and
719 writing such tables involves a lot of duplicate code, e.g.::
720
721     >>> class Person(models.Model):
722     ...     first_name = models.CharField(max_length=200)
723     ...     last_name = models.CharField(max_length=200)
724     ...     user = models.ForeignKey("auth.User")
725     ...     dob = models.DateField()
726     ...
727     >>> class PersonTable(tables.Table):
728     ...     first_name = tables.Column()
729     ...     last_name = tables.Column()
730     ...     user = tables.Column()
731     ...     dob = tables.Column()
732     ...
733
734 Often a table will become quite complex after time, e.g. `table.render_foo`_,
735 changing ``verbose_name`` on columns, or adding an extra
736 :class:`~.CheckBoxColumn`.
737
738 ``django-tables2`` offers the :attr:`.Table.Meta.model` option to ease the pain.
739 The ``model`` option causes the table automatically generate columns for the
740 fields in the model. This means that the above table could be re-written as
741 follows::
742
743     >>> class PersonTable(tables.Table):
744     ...     class Meta:
745     ...         model = Person
746     ...
747     >>> PersonTable.base_columns.keys()
748     ['first_name', 'last_name', 'user', 'dob']
749
750 If you want to customise one of the columns, simply define it the way you would
751 normally::
752
753     >>> from django_tables2 import A
754     >>> class PersonTable(tables.Table):
755     ...     user = tables.LinkColumn("admin:auth_user_change", args=[A("user.pk")])
756     ...
757     ...     class Meta:
758     ...         model = Person
759     ...
760     >>> PersonTable.base_columns.keys()
761     ['first_name', 'last_name', 'dob', 'user']
762
763 It's not immediately obvious but if you look carefully you'll notice that the
764 order of the fields has now changed -- ``user`` is now last, rather than
765 ``dob``. This follows the same behaviour of Django's model forms, and can be
766 fixed in a similar way -- the :attr:`.Table.Meta.sequence` option::
767
768     >>> class PersonTable(tables.Table):
769     ...     user = tables.LinkColumn("admin:auth_user_change", args=[A("user.pk")])
770     ...
771     ...     class Meta:
772     ...         model = Person
773     ...         sequence = ("first_name", "last_name", "user", "dob")
774     ...
775     >>> PersonTable.base_columns.keys()
776     ['first_name', 'last_name', 'user', 'dob']
777
778 … or use a shorter approach that makes use of the special ``"..."`` item::
779
780     >>> class PersonTable(tables.Table):
781     ...     user = tables.LinkColumn("admin:auth_user_change", args=[A("user.pk")])
782     ...
783     ...     class Meta:
784     ...         model = Person
785     ...         sequence = ("...", "dob")
786     ...
787     >>> PersonTable.base_columns.keys()
788     ['first_name', 'last_name', 'user', 'dob']
789
790
791 API Reference
792 =============
793
794 :class:`Accessor` Objects:
795 --------------------------
796
797 .. autoclass:: django_tables2.utils.Accessor
798     :members:
799
800
801 :class:`Table` Objects:
802 -----------------------
803
804 .. autoclass:: django_tables2.tables.Table
805
806
807 :class:`Table.Meta` Objects:
808 ----------------------------
809
810 .. class:: Table.Meta
811
812     Provides a way to define *global* settings for table, as opposed to
813     defining them for each instance.
814
815     .. attribute:: attrs
816
817         Allows custom HTML attributes to be specified which will be added to
818         the ``<table>`` tag of any table rendered via
819         :meth:`~django_tables2.tables.Table.as_html` or the
820         :ref:`template-tags.render_table` template tag.
821
822         :type: ``dict``
823         :default: ``{}``
824
825         This is typically used to enable a theme for a table (which is done by
826         adding a CSS class to the ``<table>`` element). i.e.::
827
828             class SimpleTable(tables.Table):
829                 name = tables.Column()
830
831                 class Meta:
832                     attrs = {"class": "paleblue"}
833
834         .. note::
835
836             This functionality is also available via the ``attrs`` keyword
837             argument to a table's constructor.
838
839     .. attribute:: empty_text
840
841         Defines the text to display when the table has no rows.
842
843         :type: ``string``
844         :default: ``None``
845
846         If the table is empty and ``bool(empty_text)`` is ``True``, a row is
847         displayed containing ``empty_text``. This is allows a message such as
848         *There are currently no FOO.* to be displayed.
849
850         .. note::
851
852             This functionality is also available via the ``empty_text`` keyword
853             argument to a table's constructor.
854
855     .. attribute:: exclude
856
857         Defines which columns should be excluded from the table. This is useful
858         in subclasses to exclude columns in a parent.
859
860         :type: tuple of ``string`` objects
861         :default: ``()``
862
863         Example::
864
865             >>> class Person(tables.Table):
866             ...     first_name = tables.Column()
867             ...     last_name = tables.Column()
868             ...
869             >>> Person.base_columns
870             {'first_name': <django_tables2.columns.Column object at 0x10046df10>,
871             'last_name': <django_tables2.columns.Column object at 0x10046d8d0>}
872             >>> class ForgetfulPerson(Person):
873             ...     class Meta:
874             ...         exclude = ("last_name", )
875             ...
876             >>> ForgetfulPerson.base_columns
877             {'first_name': <django_tables2.columns.Column object at 0x10046df10>}
878
879         .. note::
880
881             This functionality is also available via the ``exclude`` keyword
882             argument to a table's constructor.
883
884             However, unlike some of the other ``Meta`` options, providing the
885             ``exclude`` keyword to a table's constructor **won't override** the
886             ``Meta.exclude``. Instead, it will be effectively be *added*
887             to it. i.e. you can't use the constructor's ``exclude`` argument to
888             *undo* an exclusion.
889
890     .. attribute:: model
891
892         A model to inspect and automatically create corresponding columns.
893
894         :type: Django model
895         :default: ``None``
896
897         This option allows a Django model to be specified to cause the table to
898         automatically generate columns that correspond to the fields in a
899         model.
900
901     .. attribute:: order_by
902
903         The default ordering. e.g. ``('name', '-age')``. A hyphen ``-`` can be
904         used to prefix a column name to indicate *descending* order.
905
906         :type: ``tuple``
907         :default: ``()``
908
909         .. note::
910
911             This functionality is also available via the ``order_by`` keyword
912             argument to a table's constructor.
913
914     .. attribute:: sequence
915
916         The sequence of the table columns. This allows the default order of
917         columns (the order they were defined in the Table) to be overridden.
918
919         :type: any iterable (e.g. ``tuple`` or ``list``)
920         :default: ``()``
921
922         The special item ``"..."`` can be used as a placeholder that will be
923         replaced with all the columns that weren't explicitly listed. This
924         allows you to add columns to the front or back when using inheritence.
925
926         Example::
927
928             >>> class Person(tables.Table):
929             ...     first_name = tables.Column()
930             ...     last_name = tables.Column()
931             ...
932             ...     class Meta:
933             ...         sequence = ("last_name", "...")
934             ...
935             >>> Person.base_columns.keys()
936             ['last_name', 'first_name']
937
938         The ``"..."`` item can be used at most once in the sequence value. If
939         it's not used, every column *must* be explicitly included. e.g. in the
940         above example, ``sequence = ("last_name", )`` would be **invalid**
941         because neither ``"..."`` or ``"first_name"`` were included.
942
943         .. note::
944
945             This functionality is also available via the ``sequence`` keyword
946             argument to a table's constructor.
947
948     .. attribute:: sortable
949
950         Whether columns are by default sortable, or not. i.e. the fallback for
951         value for a column's sortable value.
952
953         :type: ``bool``
954         :default: ``True``
955
956         If the ``Table`` and ``Column`` don't specify a value, a column's
957         ``sortable`` value will fallback to this. object specify. This provides
958         an easy mechanism to disable sorting on an entire table, without adding
959         ``sortable=False`` to each ``Column`` in a ``Table``.
960
961         .. note::
962
963             This functionality is also available via the ``sortable`` keyword
964             argument to a table's constructor.
965
966
967 :class:`TableData` Objects:
968 ------------------------------
969
970 .. autoclass:: django_tables2.tables.TableData
971     :members: __init__, order_by, __getitem__, __len__
972
973
974 :class:`Column` Objects:
975 ------------------------
976
977 .. autoclass:: django_tables2.columns.Column
978
979
980 :class:`CheckBoxColumn` Objects:
981 --------------------------------
982
983 .. autoclass:: django_tables2.columns.CheckBoxColumn
984     :members:
985
986
987 :class:`LinkColumn` Objects:
988 ----------------------------
989
990 .. autoclass:: django_tables2.columns.LinkColumn
991     :members:
992
993
994 :class:`TemplateColumn` Objects:
995 --------------------------------
996
997 .. autoclass:: django_tables2.columns.TemplateColumn
998     :members:
999
1000
1001 :class:`BoundColumns` Objects
1002 -----------------------------
1003
1004 .. autoclass:: django_tables2.columns.BoundColumns
1005     :members: all, items, sortable, visible, __iter__,
1006               __contains__, __len__, __getitem__
1007
1008
1009 :class:`BoundColumn` Objects
1010 ----------------------------
1011
1012 .. autoclass:: django_tables2.columns.BoundColumn
1013     :members:
1014
1015
1016 :class:`BoundRows` Objects
1017 --------------------------
1018
1019 .. autoclass:: django_tables2.rows.BoundRows
1020     :members: __iter__, __len__, count
1021
1022
1023 :class:`BoundRow` Objects
1024 -------------------------
1025
1026 .. autoclass:: django_tables2.rows.BoundRow
1027     :members: __getitem__, __contains__, __iter__, record, table
1028
1029
1030 :class:`AttributeDict` Objects
1031 ------------------------------
1032
1033 .. autoclass:: django_tables2.utils.AttributeDict
1034     :members:
1035
1036
1037 :class:`OrderBy` Objects
1038 ------------------------
1039
1040 .. autoclass:: django_tables2.utils.OrderBy
1041     :members:
1042
1043
1044 :class:`OrderByTuple` Objects
1045 -----------------------------
1046
1047 .. autoclass:: django_tables2.utils.OrderByTuple
1048     :members: __unicode__, __contains__, __getitem__, cmp
1049
1050
1051 Glossary
1052 ========
1053
1054 .. glossary::
1055
1056     accessor
1057         Refers to an :class:`~django_tables2.utils.Accessor` object
1058
1059     bare orderby
1060         The non-prefixed form of an :class:`~django_tables2.utils.OrderBy`
1061         object. Typically the bare form is just the ascending form.
1062
1063         Example: ``age`` is the bare form of ``-age``
1064
1065     column name
1066         The name given to a column. In the follow example, the *column name* is
1067         ``age``.
1068
1069         .. code-block:: python
1070
1071             class SimpleTable(tables.Table):
1072                 age = tables.Column()
1073
1074     table
1075         The traditional concept of a table. i.e. a grid of rows and columns
1076         containing data.
1077
1078     view
1079         A Django view.
1080
1081     record
1082         A single Python object used as the data for a single row.
1083
1084     render
1085         The act of serialising a :class:`~django_tables2.tables.Table` into
1086         HTML.
1087
1088     template
1089         A Django template.
1090
1091     table data
1092         An interable of :term:`records <record>` that
1093         :class:`~django_tables2.tables.Table` uses to populate its rows.