Skip to content

Commit

Permalink
Merge pull request #187 from mbertheau/dont-titlise
Browse files Browse the repository at this point in the history
assuming title case is good for headers is too bold
  • Loading branch information
bradleyayers committed Mar 7, 2014
2 parents 7853b24 + bafce58 commit bc9da04
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 33 deletions.
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

0 comments on commit bc9da04

Please sign in to comment.