Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assuming title case is good for headers is too bold #187

Merged
merged 1 commit into from
Mar 7, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ globally, use::
Change log
==========

- `BoundColumn.verbose_name` now titlises only if no verbose_name was given.
``verbose_name`` is used verbatim.

v0.15.0
-------

Expand Down
30 changes: 5 additions & 25 deletions django_tables2/columns/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from __future__ import absolute_import, unicode_literals
from django.db.models.fields import FieldDoesNotExist
from django.utils.datastructures import SortedDict
from django.utils.safestring import SafeData
from django_tables2.templatetags.django_tables2 import title
from django_tables2.utils import A, AttributeDict, OrderBy, OrderByTuple
from itertools import islice
Expand Down Expand Up @@ -116,9 +115,6 @@ class Column(object): # pylint: disable=R0902
:type: `unicode`
This should not defined in title case, but rather natural case. It is
converted to title case for use in column headers.
.. attribute:: visible
Expand Down Expand Up @@ -188,9 +184,7 @@ def header(self):
"""
The value used for the column heading (e.g. inside the ``<th>`` tag).
By default this titlises the `~.Column.verbose_name`. If
`~.Column.verbose_name` is an instance of `~.safestring.SafeData`, it's
used unmodified.
By default this returns `~.Column.verbose_name`.
:returns: `unicode` or `None`
Expand All @@ -203,12 +197,7 @@ def header(self):
accessing that first) when this property doesn't return something
useful.
"""
if self.verbose_name:
if isinstance(self.verbose_name, SafeData):
# If the author has used mark_safe, we're going to assume the
# author wants the value used verbatim.
return self.verbose_name
return title(self.verbose_name)
return self.verbose_name

def render(self, value):
"""
Expand Down Expand Up @@ -350,13 +339,7 @@ def header(self):
if column_header:
return column_header
# fall back to automatic best guess
verbose_name = self.verbose_name # avoid calculating multiple times
if isinstance(verbose_name, SafeData):
# If the verbose_name has come from a model field, it's possible
# that the author used mark_safe to include HTML in the value. If
# this is the case, we leave it verbatim.
return verbose_name
return title(verbose_name)
return self.verbose_name

@property
def order_by(self):
Expand Down Expand Up @@ -453,25 +436,22 @@ def orderable(self):
@property
def verbose_name(self):
"""
Return the verbose name for this column, or fallback to prettified
Return the verbose name for this column, or fallback to the titlised
column name.
If the table is using queryset data, then use the corresponding model
field's `~.db.Field.verbose_name`. If it's traversing a relationship,
then get the last field in the accessor (i.e. stop when the
relationship turns from ORM relationships to object attributes [e.g.
person.upper should stop at person]).
If the model field's `~.db.Field.verbose_name` is a
`~.safestring.SafeData`, it's used unmodified.
"""
# Favor an explicit defined verbose_name
if self.column.verbose_name:
return self.column.verbose_name

# This is our reasonable fallback, should the next section not result
# in anything useful.
name = self.name.replace('_', ' ')
name = title(self.name.replace('_', ' '))

# Try to use a tmodel field's verbose_name
if hasattr(self.table.data, 'queryset'):
Expand Down
3 changes: 2 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@ Customising column headings
===========================

The header cell for each column comes from `~.Column.header`. By default this
method returns a titlised version of the `~.Column.verbose_name`.
method returns `~.Column.verbose_name`, falling back to the titlised attribute
name of the column in the table class.

When using queryset data and a verbose name hasn't been explicitly
defined for a column, the corresponding model field's verbose name will be
Expand Down
4 changes: 2 additions & 2 deletions tests/columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,14 @@ class TestTable(tables.Table):


@general.test
def column_header_should_use_titlised_verbose_name():
def column_header_should_use_titlised_verbose_name_unless_given_explicitly():
class SimpleTable(tables.Table):
basic = tables.Column()
acronym = tables.Column(verbose_name="has FBI help")

table = SimpleTable([])
assert table.columns["basic"].header == "Basic"
assert table.columns["acronym"].header == "Has FBI Help"
assert table.columns["acronym"].header == "has FBI help"


@general.test
Expand Down
10 changes: 5 additions & 5 deletions tests/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ def attrs(xml):
class CountryTable(tables.Table):
name = tables.Column()
capital = tables.Column(orderable=False,
verbose_name=ugettext_lazy("capital"))
population = tables.Column(verbose_name='population size')
verbose_name=ugettext_lazy("Capital"))
population = tables.Column(verbose_name='Population Size')
currency = tables.Column(visible=False)
tld = tables.Column(visible=False, verbose_name='domain')
tld = tables.Column(visible=False, verbose_name='Domain')
calling_code = tables.Column(accessor='cc',
verbose_name='phone ext.')
verbose_name='Phone Ext.')


MEMORY_DATA = [
Expand Down Expand Up @@ -182,7 +182,7 @@ def render_table_supports_queryset():
'request': build_request('/')}))

root = parse(html)
assert [e.text for e in root.findall('.//thead/tr/th/a')] == ["ID", "Name", "Mayor"]
assert [e.text for e in root.findall('.//thead/tr/th/a')] == ["ID", "name", "mayor"]
td = [[td.text for td in tr.findall('td')] for tr in root.findall('.//tbody/tr')]
db = []
for region in Region.objects.all():
Expand Down