Change log

2.0.0a1 (2018-04-12)

  • Fixed translation of 'previous' for some languages (fixes #563)

django-tables2 2.0.0a0 (2018-04-10)

  • Cleaned up templates to add consistancy in what is presented accross all templates.
  • Added bootstrap4.html template
  • Fixed translation inconsistancies.

breaking changes

  • Appearance of the paginators might be different from the current 1.x templates. Use a custom template if you need to keep the appearance the same.
  • Removed the template argument to the table constructor, use template_name instead.
  • Stopped adding column names to the class attribute of table cells (<td> tags) by default. Previous behaviour can be restored by using this method on your custom table:
class MyTable(tables.Table):
    # columns
    def get_column_class_names(self, classes_set, bound_column):
        classes_set = super(MyTable, self).get_column_class_names(classes_set, bound_column)
        return classes_set
  • verbose_names derived from model fields are not passed through title() anymore, only the first character is converted to upper case. This follows Django's convention for verbose field names: "The convention is not to capitalize the first letter of the verbose_name. Django will automatically capitalize the first letter where it needs to." (Fixes #475 and #491)

1.21.2 (2018-03-26)

  • Moved table instantiation from get_context_data to get_tables #554 by @sdolemelipone
  • Pass request as kwarg to template.render(), rather than as part of context. (fixes #552)

1.21.1 (2018-03-12)

  • Do not perform extra COUNT() queries for non-paginated tables. Fixes #551

1.21.0 (2018-03-12)

  • Add new method paginated_rows to Table to replace fallback to non-paginated rows in templates.
  • Prevent mutation of the template context {% render_table %} is called from (fixes #547) Possible breaking change: the context variables of the template {% render_table %} is called from is no longer available in the table's template. The table variable has an attribute context, which is the context of the calling template. Use {{ table.context.variable }} instead of {{ variable }}.

1.20.0 (2018-03-08)

  • Define and use get_table_data in MultiTableMixin #538 by @vCra (fixes #528)
  • Added {% export_url <format> %} template tag.
  • Allow passing a TableData-derived class to the data argument of the Table constructor, instead of a QuerySet or list of dicts.

1.19.0 (2018-02-02)

  • BoundColumn.attrs does not evaluate current_value as bool #536 by @pachewise (fixes #534)
  • Allow more flexible access to cell values (especially useful for django templates) (fixes #485)

1.18.0 (2018-01-27)

  • Follow relations when detecting column type for fields in Table.Meta.fields (fixes #498)
  • Renamed Table.Meta.template to template_name (with deprecation warning for the former) #542 (fixes #520)
  • Added Czech translation #533 by @OndraRehounek
  • Added table_factory #532 by @ZuluPro

1.17.1 (2017-12-14)

  • Fix typo in for extras_require.

1.17.0 (2017-12-14)

  • Dropped support for Django 1.8, 1.9 and 1.10.
  • Add extra_context argument to TemplateColumn #509 by @ad-m
  • Remove unnecessary cast of record to str #514, fixes #511
  • Use django.test.TestCase for all tests, and remove dependency on pytest and reorganized some tests #515
  • Remove traces of django-haystack tests from the tests, there were no actual tests.

1.16.0 (2017-11-27)

This is the last version supporting Django 1.8, 1.9 and 1.10. Django 1.8 is only supported until april 2018, so consider upgrading to Django 1.11!

  • Added tf dictionary to Column.attrs with default values for the footer, so footers now have class attribute by default #501 by @mpasternak

1.15.0 (2017-11-23)

  • Added as=varname keyword argument to the {% querystring %} template tag, fixes #481
  • Updated the tutorial to reflect current state of Django a bit better.
  • Used OrderedDict rather than dict as the parent for utils.AttributeDict to make the rendered html more consistant accross python versions.
  • Allow reading column attrs from a column's attribute, allowing easier reuse of custom column attributes (fixes #241)
  • value and record are optionally passed to the column attrs callables for data rows. #503, fixes #500

1.14.2 (2017-10-30)

  • Added a row_counter variable to the template context in TemplateColumn (fixes #448)

1.14.1 (2017-10-30)

  • Do not fail if orderable=False is passed to ManyToManyColumn()

1.14.0 (2017-10-30)

  • Added separator argument to ManyToManyColumn.
  • Allow mark_safe()'d strings from ManyToManyColumn.tranform()
  • Disabled ordering on ManyToManyColumns by default.

1.13.0 (2017-10-17)

  • Made positional data argument to the table __init__() a keyword argument to make inheritance easier. Will raise a TypeError if ommitted.

1.12.0 (2017-10-10)

1.11.0 (2017-09-15)

  • Added Hungarian translation #471 by @hmikihth.
  • Added TemplateColumn.value() and enhanced export docs (fixes #470)
  • Fixed display of pinned rows if table has no data. #477 by @khirstinova

1.10.0 (2017-06-30)

  • Added ManyToManyColumn automatically added for ManyToManyFields.

1.9.1 (2017-06-29)

  • Allow customizing the value used in Table.as_values() (when using a render_<name> method) using a value_<name> method. (fixes #458)
  • Allow excluding columns from the Table.as_values() output. (fixes #459)
  • Fixed unicode handling for columhn headers in Table.as_values()

1.9.0 (2017-06-22)

  • Allow computable attrs for <td>-tags from Table.attrs (#457, fixes #451)

1.8.0 (2017-06-17)

  • Feature: Added an ExportMixin to export table data in various export formats (CSV, XLS, etc.) using tablib.
  • Defer expanding Meta.sequence to Table.__init__, to make sequence work in combination with extra_columns (fixes #450)
  • Fixed a crash when MultiTableMixin.get_tables() returned an empty array (#454 by @pypetey

1.7.1 (2017-06-02)

  • Call before_render when rendering with the render_table template tag (fixes #447)

1.7.0 (2017-06-01)

  • Make title() lazy (#443 by @ygwain, fixes #438)
  • Fix __all__ by populating them with the names of the items to export instead of the items themself.
  • Allow adding extra columns to an instance using the extra_columns argument. Fixes #403, #70
  • Added a hook before_render to allow last-minute changes to the table before rendering.
  • Added and BoundColumns.hide() to show/hide columns on an instance of a Table.
  • Use <listlike>.verbose_name/.verbose_name_plural if it exists to name the items in the list. (fixes #166)

1.6.1 (2017-05-08)

1.6.0 (2017-05-01)

  • Add new template bootstrap-responsive.html to generate a responsive bootstrap table. (Fixes #436)

1.5.0 (2017-04-18)

Full disclosure: as of april 1st, 2017, I am an employee of Zostera, as such I will continue to maintain and improve django-tables2.

  • Made TableBase.as_values() an interator (#432 by @pziarsolo)
  • Added JSONField for data in JSON format.
  • Added __all__ in django_tables2/ and django_tables2/columns/
  • Added a setting DJANGO_TABLES2_TEMPLATE to allow project-wide overriding of the template used to render tables (fixes #434).

1.4.2 (2017-03-06)

  • Feature: Pinned rows (#411 by @djk2, fixes #406)
  • Fix an issue where ValueError was raised while using a view with a get_queryset() method defined. (fix with #423 by @desecho)

1.4.1 (2017-02-27)

  • Fix urls to screenshots in on pypi description (fixes #398)
  • Prevent superfluous spaces when a callable row_attrs['class'] returns an empty string ([#417]( by @Superman8218), fixes #416)

1.4.0 (2017-02-27)

  • Return None from Table.as_values() for missing values. #419
  • Fix ordering by custom fields, and refactor TableData #424, fixes #413
  • Revert removing TableData.__iter__() (removed in this commit), fixes #427, #361 and #421.

1.3.0 (2017-01-20)

  • Implement method Table.as_values() to get it's raw values. #394 by @intiocean
  • Fix some compatibility issues with django 2.0 #408 by djk2

1.2.9 (2016-12-21)

  • Documentation for None-column attributes #401 by @dyve

1.2.8 (2016-12-21)

  • None-column attributes on child class overwrite column attributes of parent class #400 by @dyve

1.2.7 (2016-12-12)

  • Apply title to a column's verbose_name when it is derived from a model, fixes #249. (#382 by @shawnnapora)
  • Update documentation after deprecation of STATIC_URL in django (#384, by @velaia)
  • Cleanup of the templates, making the output more equal (#381 by @ralgozino)
  • Use new location for urlresolvers in Django and add backwards compatible import (#388 by @felixxm)
  • Fix a bug where using sequence and then exclude in a child table would result in a KeyError
  • Some documentation fixes and cleanups.

1.2.6 (2016-09-06)

  • Added get_table_kwargs() method to SingleTableMixin to allow passing custom keyword arguments to the Table constructor. (#366 by @fritz-k)
  • Allow the children of TableBase render in the {% render_table %} template tag. (#377 by @shawnnapora)
  • Refactor BoundColumn attributes to allow override of CSS class names, fixes #349 (#370 by @graup). Current behaviour should be intact, we will change the default in the future so it will not add the column name to the list of CSS classes.

1.2.5 (2016-07-30)

  • Fixed an issue preventing the rest of the row being rendered if a BooleanColumn was in the table for a model without custom choices defined on the model field. (#360)

1.2.4 (2016-07-28)

1.2.3 (2016-07-05)

  • Accept text parameter in FileColumn, analogous to LinkColumn (#343 by @graup)
  • Fix TemplateColumn RemovedInDjango110Warning fixes #346.
  • Use field name in RelatedColumnLink (#350, fixes #347)

v1.2.2 (2016-06-04)

  • Allow use of custom class names for ordered columns through attrs. ( #329 by @theTarkus)
  • Column ordering queryset passthrough (#330 by @theTarkus)
  • Cleanup/restructuring of documentation, (#325)
  • Fixed an issue where explicitly defined column options where not preserved over inheritance (#339, issue #337)
  • Fixed an issue where exclude in combination with sequence raised a KeyError (#341, issue #205)

v1.2.1 (2016-05-09)

  • table footers (#323)
  • Non-field based LinkColumn only renders default value if lookup fails. (#322)
  • Accept text parameter in BaseLinkColumn-based columns. (#322)
  • Pass the table instance into SingleTableMixin's get_table_pagination (#320 by @georgema1982, fixes #319)
  • Check if the view has paginate_by before before trying to access it. (fixes #326)

v1.2.0 (2016-05-02)

  • Allow custom attributes for rows (fixes #47)

v1.1.8 (2016-05-02)

  • Ability to change the body of the <a>-tag, by passing text kwarg to the columns inheriting from BaseLinkColumn (#318 by @desecho, #322)
  • Non-field based LinkColumn only renders default value if lookup fails and text is not set. (#322, fixes #257)

v1.1.7 (2016-04-26)

  • Added Italian translation (#315 by @paolodina
  • Added Dutch translation.
  • Fixed {% blocktrans %} template whitespace issues
  • Fixed errors when using a column named items (#316)
  • Obey paginate_by (from MultipleObjectMixin) if no later pagination is defined (#242)

v1.1.6 (2016-04-02)

  • Correct error message about request context processors for current Django (#314)
  • Skipped 1.1.5 due to an error while creating the tag.

v1.1.4 (2016-03-22)

  • Fix broken if Django is not installed before django-tables2 (fixes #312)

v1.1.3 (2016-03-21)

  • Drop support for Django 1.7
  • Add argument to CheckBoxColumn to render it as checked (original PR: #208)

v1.1.2 (2016-02-16)

  • Fix BooleanColumn with choices set will always render as if True (#301)
  • Fix a bug with TemplateColumn while using cached template loader (#75)

v1.1.1 (2016-01-26)

  • Allow Meta.fields to be a list as well as a tuple (#250)
  • Call template.render with a dict in Django >= 1.8. (#298)
  • Added RelatedLinkColumn() to render links to related objects (#297)
  • Remove default value from request param to table.as_html()

v1.1.0 (2016-01-19)

  • Add tests for TimeColumn
  • Remove sortable argument for Table and Column constructors and its associated methods. Deprecated since 2012.
  • Remove deprecated aliases for attrs in CheckboxColumn.
  • Remove deprecated OrderByTuple cmp method (deprecated since 2013).
  • Add bootstrap template and (#293, fixes #141, #285)
  • Fix different html for tables with and without pagination (#293, fixes #149, #285)
  • Remove {% nospaceless %} template tag and remove wrapping template in {% spaceless %} Possible breaking change, if you use custom templates.

v1.0.7 (2016-01-03)

  • Explicitly check if column.verbose_name is not None to support empty column headers (fixes #280)
  • Cleanup the example project to make it work with modern Django versions.
  • Do not sort queryset when orderable=False (#204 by @bmihelac)
  • show_header attribute on Table allows disabling the header (#175 by @kviktor)
  • LinkColumn now tries to call get_absolute_url on a record if no viewname is provided (#283, fixes #231).
  • Add request argument to Table.as_html() to allow passing correct request objects instead of poorly generated ones #282
  • Add coverage reporting to build #282
  • Drop support for python 3.2 (because of coverage), support ends feb 2016 #282
  • move build_request from django_table2.utils to tests.utils and amend tests #282

v1.0.6 (2015-12-29)

  • Support for custom text value in LinkColumn (#277 by @toudi)
  • Refactor LinkColumn.render_link() to not escape twice #279
  • Removed Attrs (wrapper for dict), deprecated on 2012-09-18
  • Convert to rst in to make PyPI look nice (fixes #97)

v1.0.5 (2015-12-17)

  • First version released by new maintainer @jieter
  • Dropped support for django 1.5 and 1.6, add python 3.5 with django 1.8 and 1.9 to the build matrix (#273)
  • Prevent SingleTableView from calling get_queryset twice. (fixes #155)
  • Don't call managers when resolving accessors. (#214 by @mbertheau, fixes #211)

v1.0.4 (2015-05-09)

  • Fix bug in retrieving field.verbose_name under Django 1.8.


  • Remove setup.cfg as PyPI doesn't actually support it, instead it's a distutils2 thing that's been discontinued.


  • Add setup.cfg to declare for PyPI.


  • Convert README to markdown so it's formatted nicely on PyPI.


  • Travis CI builds pass.
  • Added Python 3.4 support.
  • Added Django 1.7 and Django 1.8 support.
  • Convert tests to using py.test.


  • Django 1.8 fixes
  • BoundColumn.verbose_name now titlises only if no verbose_name was given. verbose_name is used verbatim.
  • Add max_length attribute to person CharField
  • Add Swedish translation
  • Update docs presentation on readthedocs


  • Add UK, Russian, Spanish, Portuguese, and Polish translations
  • Add support for computed table attrs.


  • querystring and seturlparam template tags now require the request to be in the context (backwards incompatible) -- #127
  • Add Travis CI support
  • Add support for Django 1.5
  • Add L10N control for columns #120 (ignored in < Django 1.3)
  • Drop Python 2.6.4 support in favour of Python 3.2 support
  • Non-queryset data ordering is different between Python 3 and 2. When comparing different types, their truth values are now compared before falling back to string representations of their type.


  • Add FileColumn.


  • When resolving an accessor, all exceptions are smothered into None.


  • Improve performance by removing unnecessary queries
  • Simplified pagination:
    • is an instance attribute (no longer @property)
    • Exceptions raised by paginators (e.g. EmptyPage) are no longer smothered by
    • Pagination exceptions are raised by Table.paginate
    • RequestConfig can handles pagination errors silently, can be disabled by including silent=False in the paginate argument value
  • Add DateTimeColumn and DateColumn to handle formatting datetime and timezones.
  • Add BooleanColumn to handle bool values
  • render_table can now build and render a table for a queryset, rather than needing to be passed a table instance
  • Table columns created automatically from a model now use specialised columns
  • Column.render is now skipped if the value is considered empty, the default value is used instead. Empty values are specified via Column.empty_values, by default is (None, '') (backward incompatible)
  • Default values can now be specified on table instances or Table.Meta
  • Accessor's now honor alters_data during resolving. Fixes issue that would delete all your data when a column had an accessor of delete
  • Add default and value to context of TemplateColumn
  • Add cardinality indication to the pagination area of a table
  • Attrs is deprecated, use dict instead


  • Add URLColumn to render URLs in a data source into hyperlinks
  • Add EmailColumn to render email addresses into hyperlinks
  • TemplateColumn can now Django's template loaders to render from a file


  • Fix more bugs on Python 2.6.4, all tests now pass.


  • Fix issues for Python 2.6.4 -- thanks Steve Sapovits & brianmay
  • Reduce Django 1.3 dependency to Table.as_html -- thanks brianmay


  • Fix to include example templates, thanks TWAC.
  • Upgrade django-attest to fix problem with tests on Django 1.3.1


  • Fixed support for Django 1.4's paginator (thanks koledennix)
  • Some juggling of internal implementation. TableData now supports slicing and returns new TableData instances. BoundRows now takes a single argument data (a TableData instance).
  • Add support for get_pagination on SingleTableMixin.
  • SingleTableMixin and SingleTableView are now importable directly from django_tables2.


  • Renamed BoundColumn.order_by to order_by_alias and never returns None (Backwards incompatible). Templates are affected if they use something like:

    {% querystring table.prefixed_order_by_field=column.order_by.opposite| %}

    Which should be rewritten as:

    {% querystring %}
  • Added next shortcut to OrderBy returned from BoundColumn.order_by_alias

  • Added OrderByTuple.get()

  • Deprecated BoundColumn.sortable, Column.sortable, Table.sortable, sortable CSS class, BoundColumns.itersortable, BoundColumns.sortable; use orderable instead of sortable.

  • Added BoundColumn.is_ordered

  • Introduced concept of an order by alias, see glossary in the docs for details.


  • Fix bug that caused an ordered column's th to have no HTML attributes.


  • Updated example project to add colspan on footer cell so table border renders correctly in Webkit.
  • Fix regression that caused 'sortable' class on .
  • Table.init no longer always calls .order_by() on querysets, fixes #55. This does introduce a slight backwards incompatibility. Table.order_by now has the possibility of returning None, previously it would always return an OrderByTuple.
  • now uses super()
  • Testing now requires pylint and Attest >=0.5.3


  • Fix regression that caused column verbose_name values that were marked as safe to be escaped. Now any verbose_name values that are instances of SafeData are used unmodified.


  • Fix regression in SingleTableMixin.
  • Remove stray print statement.


  • SingleTableView now uses RequestConfig. This fixes issues with order_by_field, page_field, and per_page_field not being honored.
  • Add Table.Meta.per_page and change Table.paginate to use it as default.
  • Add title template filter. It differs from Django's built-in title filter because it operates on an individual word basis and leaves words containing capitals untouched. Warning: use {% load ... from ... %} to avoid inadvertantly replacing Django's builtin title template filter.
  • BoundColumn.verbose_name no longer does capfirst, titlising is now the responsbility of Column.header.
  • BoundColumn.__unicode__ now uses BoundColumn.header rather than BoundColumn.verbose_name.


  • Fix version in (doh)


  • Add support for column attributes (see Attrs)
  • Add BoundRows.items() to yield (bound_column, cell) pairs
  • Tried to make docs more concise. Much stronger promotion of using RequestConfig and {% querystring %}


  • Removed random 'print' statements.
  • Tweaked 'paleblue' theme css to be more flexible:
    • removed whitespace: no-wrap
    • header background image to support more than 2 rows of text


  • Fixed stupid import mistake. Tests didn't pick it up due to them ignoring ImportError.


  • SingleTableView now inherits from ListView which enables automatic foo_list.html template name resolution (thanks dramon for reporting)
  • render_table template tag no suppresses exceptions when DEBUG=True


  • Fixed bug in render_table when giving it a template (issue #41)


  • Added translation support in the default template via {% trans %}
  • Removed basic_table.html, Table.as_html() now renders table.html but will clobber the querystring of the current request. Use the render_table template tag instead
  • render_table now supports an optional second argument -- the template to use when rendering the table
  • Table now supports declaring which template to use when rendering to HTML
  • Django >=1.3 is now required
  • Added support for using django-haystack's SearchQuerySet as a data source
  • The default template table.html now includes block tags to make it easy to extend to change small pieces
  • Fixed table template parsing problems being hidden due to a subsequent exception being raised
  • Http404 exceptions are no longer raised during a call to Table.paginate(), instead it now occurs when is accessed
  • Fixed bug where a table couldn't be rendered more than once if it was paginated
  • Accessing now returns a new page every time, rather than reusing a single object


  • Tables now support using both sequence and exclude (issue #32).
  • Sequence class moved to django_tables2/
  • Table instances now support modification to the exclude property.
  • Removed BoundColumns._spawn_columns.
  •, Table.rows, and Table.columns are now attributes rather than properties.