Skip to content

Commit

Permalink
Refactor BoundColumn attributes to allow override of class names. jie…
Browse files Browse the repository at this point in the history
  • Loading branch information
graup committed Aug 15, 2016
1 parent 6e43737 commit ae4a894
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 15 deletions.
46 changes: 31 additions & 15 deletions django_tables2/columns/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ class BoundColumn(object):
means that a `.BoundColumn` knows the *"variable name"* given to the
`.Column` when it was declared on the `.Table`.
For convenience, all `.Column` properties are available from thisclass.
For convenience, all `.Column` properties are available from this class.
:type table: `.Table` object
:param table: the table in which this column exists
Expand Down Expand Up @@ -282,33 +282,48 @@ def attrs(self):
# Update attrs to prefer column's attrs rather than table's
attrs.update(dict(self.column.attrs))

# Column ordering class names
ordering_class = attrs.get('th', {}).get('_ordering', {})

# Find the relevant th attributes (fall back to cell if th isn't
# explicitly specified).
attrs['th'] = AttributeDict(attrs.get('th', attrs.get('cell', {})))
attrs['td'] = AttributeDict(attrs.get('td', attrs.get('cell', {})))

# make set of existing classes.
th_class = set((c for c in attrs['th'].get('class', '').split(' ') if c))
td_class = set((c for c in attrs['td'].get('class', '').split(' ') if c))
# Override/add classes
attrs['th']['class'] = self.get_th_class_name(attrs['th'])
attrs['td']['class'] = self.get_td_class_name(attrs['td'])

return attrs

def get_class_name(self):
"""
Returns the HTML class attribute used for both header and data cell
"""
return self.name

def get_td_class_name(self, td_attrs):
"""
Returns the HTML class attribute for a data cell in this column
"""
td_class = set((c for c in td_attrs.get('class', '').split(' ') if c))
td_class.add(self.get_class_name())
return ' '.join(sorted(td_class))

def get_th_class_name(self, th_attrs):
"""
Returns the HTML class attribute for a header cell in this column
"""
th_class = set((c for c in th_attrs.get('class', '').split(' ') if c))
th_class.add(self.get_class_name())

# add classes for ordering
ordering_class = th_attrs.get('_ordering', {})
if self.orderable:
th_class.add(ordering_class.get('orderable', 'orderable'))
if self.is_ordered:
th_class.add(ordering_class.get('descending', 'desc')
if self.order_by_alias.is_descending
else ordering_class.get('ascending', 'asc'))

# Always add the column name as a class
th_class.add(self.name)
td_class.add(self.name)

attrs['th']['class'] = ' '.join(sorted(th_class))
attrs['td']['class'] = ' '.join(sorted(td_class))
return attrs
return ' '.join(sorted(th_class))

@property
def default(self):
Expand Down Expand Up @@ -494,8 +509,9 @@ class BoundColumns(object):
def __init__(self, table):
self.table = table
self.columns = OrderedDict()
bc_class = getattr(self.table._meta, 'bound_column_class', BoundColumn)
for name, column in six.iteritems(table.base_columns):
self.columns[name] = bc = BoundColumn(table, column, name)
self.columns[name] = bc = bc_class(table, column, name)
bc.render = getattr(table, 'render_' + name, column.render)
bc.order = getattr(table, 'order_' + name, column.order)

Expand Down
2 changes: 2 additions & 0 deletions django_tables2/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ def __init__(self, options=None):
self.template = getattr(options, 'template', 'django_tables2/table.html')
self.localize = getattr(options, 'localize', ())
self.unlocalize = getattr(options, 'unlocalize', ())
self.bound_column_class = getattr(options, 'bound_column_class',
columns.BoundColumn)


class TableBase(object):
Expand Down
28 changes: 28 additions & 0 deletions tests/columns/test_general.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,31 @@ class MyTableC(MyTable):

assert table.columns['item1'].verbose_name == 'Nice column name'
assert tableC.columns['item1'].verbose_name == 'New nice column name'


def test_override_bound_column():
'''
We can override the class used for bound columns to control the
output of CSS class names
'''
class BoundColumnOverride(tables.columns.BoundColumn):
def get_class_name(self):
return 'prefix-' + self.name

class MyTable(tables.Table):
population = tables.Column(verbose_name='Population')

class Meta:
bound_column_class = BoundColumnOverride

TEST_DATA = [
{'name': 'Belgium', 'population': 11200000},
{'name': 'Luxembourgh', 'population': 540000},
{'name': 'France', 'population': 66000000},
]

table = MyTable(TEST_DATA)
html = table.as_html(build_request())
print(html)

assert '<td class="prefix-population">11200000</td>' in html

0 comments on commit ae4a894

Please sign in to comment.