Skip to content

Commit

Permalink
Adds support for header_value for export header
Browse files Browse the repository at this point in the history
  • Loading branch information
5tefan committed Oct 21, 2024
1 parent f39cfd7 commit adf5a89
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 4 deletions.
28 changes: 28 additions & 0 deletions django_tables2/columns/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,26 @@ def header(self):
"""
return self.verbose_name

@property
def header_value(self):
"""
The value used for the column heading in exports.
By default this returns `~.Column.header`.
:returns: `unicode` or `None`
.. note::
This property typically is not accessed directly when a table is
rendered. Instead, `.BoundColumn.header_value` is accessed which
in turn accesses this property. This allows the header to fallback
to the column name (it is only available on a `.BoundColumn` object
hence accessing that first) when this property doesn't return something
useful.
"""
return self.header

def footer(self, bound_column, table):
"""Return the content of the footer, if specified."""
footer_kwargs = {"column": self, "bound_column": bound_column, "table": table}
Expand Down Expand Up @@ -556,6 +576,14 @@ def header(self):
# fall back to automatic best guess
return self.verbose_name

@property
def header_value(self):
"""The contents of the header for this column in an export."""
column_header_value = self.column.header_value
if column_header_value:
return column_header_value
return self.header

@property
def footer(self):
"""The contents of the footer cell for this column."""
Expand Down
2 changes: 1 addition & 1 deletion django_tables2/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ def value_name(self, value):
if not (column.column.exclude_from_export or column.name in exclude_columns)
]

yield [force_str(column.header, strings_only=True) for column in columns]
yield [force_str(column.header_value, strings_only=True) for column in columns]

for row in self.rows:
yield [
Expand Down
22 changes: 19 additions & 3 deletions docs/pages/custom-data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ Please refer to `.Table.as_values` for an example.
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::
Defining a column subclass allows further customization and 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
>>>
Expand Down Expand Up @@ -186,3 +186,19 @@ For complicated columns, you may want to return HTML from the
... def render(self, value):
... return format_html('<img src="/media/img/{}.jpg" />', value)
...

When subclassing a column, the header in the html table can be customized by
overriding :meth:`~Column.header`. The header value for exports can be independently
customized using :meth:`~Column.render_value`.


>>> from django.utils.html import format_html
>>>
>>> class PartyColumn(tables.Column):
... @property
... def header(self):
... return format_html('<div><marquee>PaRtY!</marquee></div>')
...
... @property
... def header_value(self):
... return "party"
4 changes: 4 additions & 0 deletions docs/pages/export.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ By default, it just calls the `render()` method on that column.
If your custom column produces HTML, you should override this method and return
the actual value.

For column headers, similarly sometimes :ref:Column.header`-may include html which
would be inappropriate to include in an export. For this case, the `:ref:Column.header_value`
can be used to override the column header only in exports.


Including and excluding columns
-------------------------------
Expand Down
16 changes: 16 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,22 @@ def value_country(self, value):

self.assertEqual(list(Table(self.AS_VALUES_DATA).as_values()), expected)

def test_as_value_header_value(self):
class CustomColumn(tables.Column):

@property
def header_value(self):
return "CUSTOM"

class Table(tables.Table):
name = tables.Column()
country = CustomColumn()

expected = [["Name", "CUSTOM"]] + [[r["name"], r["country"]] for r in self.AS_VALUES_DATA]
table = Table(self.AS_VALUES_DATA)

self.assertEqual(list(table.as_values()), expected)

def test_as_values_accessor_relation(self):
programmer = Occupation.objects.create(name="Programmer")
henk = Person.objects.create(
Expand Down

0 comments on commit adf5a89

Please sign in to comment.