Skip to content

Commit

Permalink
Allow use of custom class names for ordered columns through header at… (
Browse files Browse the repository at this point in the history
#329)

* Allow use of custom class names for ordered columns through header attributes
* Tests, fix wrong attribute dict being used
* Custom column header class names -- alternative approach
  - Remove header_attrs from table constructor
* Fix check errors
 - Remove attrs comment?
 - Rename blocklist to blacklist
 - New assert, verify table's class does not get put into th's class
* Docs
* Update column-headers-and-footers.rst
  • Loading branch information
thetarkus authored and jieter committed May 23, 2016
1 parent 772604c commit d9ebdfc
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 5 deletions.
16 changes: 12 additions & 4 deletions django_tables2/columns/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,14 @@ def attrs(self):
what's actually defined in the column attrs. This makes writing
templates easier.
"""
# Work on a copy of the attrs object since we're tweaking stuff
attrs = dict(self.column.attrs)
# Start with table's attrs; Only 'th' and 'td' attributes will be used
attrs = dict(self.table.attrs)

# 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).
Expand All @@ -328,9 +334,11 @@ def attrs(self):

# add classes for ordering
if self.orderable:
th_class.add('orderable')
th_class.add(ordering_class.get('orderable', 'orderable'))
if self.is_ordered:
th_class.add('desc' if self.order_by_alias.is_descending else 'asc')
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)
Expand Down
4 changes: 3 additions & 1 deletion django_tables2/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,10 @@ def as_html(self):
:rtype: `~django.utils.safestring.SafeUnicode` object
"""

blacklist = ('th', 'td', '_ordering')
return mark_safe(' '.join(['%s="%s"' % (k, escape(v if not callable(v) else v()))
for k, v in six.iteritems(self)]))
for k, v in six.iteritems(self) if k not in blacklist]))


def segment(sequence, aliases):
Expand Down
57 changes: 57 additions & 0 deletions docs/pages/column-headers-and-footers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,63 @@ As you can see in the last example (region name), the results are not always
desirable when an accessor is used to cross relationships. To get around this
be careful to define `.Column.verbose_name`.

Changing class names for ordered column headers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When a column is ordered in an ascending state there needs to be a way to show
it in the interface. django-tables2 does this by adding an `asc` class for
ascending or a `desc` class for descending. It should also be known that any
orderable column is added with an `orderable` class to the column header.

Sometimes there may be a need to change these default classes.

On the `attrs` attribute of the table, you can add a `th` key with the value of
a dictionary. Within that `th` dictionary, you may add an `_ordering` key also
with the value of a dictionary.

The `_ordering` element is optional and all elements within it are optional.
Inside you can have an `orderable` element, which will change the default
`orderable` class name. You can also have `ascending` which will will change the
default `asc` class name. And lastly, you can have `descending` which will
change the default `desc` class name.

Example::

class Table(tables.Table):
Meta:
attrs = {
'th' : {
'_ordering': {
'orderable': 'sortable', # Instead of `orderable`
'ascending': 'ascend', # Instead of `asc`
'descending': 'descend' # Instead of `desc`
}
}
}


It can also be specified at initialization using the `attrs` for both: table and
column::

ATTRIBUTES = {
'th' : {
'_ordering': {
'orderable': 'sortable', # Instead of `orderable`
'ascending': 'ascend', # Instead of `asc`
'descending': 'descend' # Instead of `desc`
}
}
}

table = tables.Table(queryset, attrs=ATTRIBUTES)

# OR

class Table(tables.Table):
my_column = tables.Column(attrs=ATTRIBUTES)




Adding column footers
=====================
Expand Down
76 changes: 76 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,82 @@ class Table(tables.Table):
assert table.rows[3].get_cell('country') == 'Australia'


def test_table_ordering_attributes():
class Table(tables.Table):
alpha = tables.Column()
beta = tables.Column()

table = Table(MEMORY_DATA, attrs={
'th': {
'class': 'custom-header-class',
'_ordering': {
'orderable': 'sortable',
'ascending': 'ascend',
'descending': 'descend',
},
},
}, order_by='alpha')

assert 'sortable' in table.columns[0].attrs['th']['class']
assert 'ascend' in table.columns[0].attrs['th']['class']
assert 'custom-header-class' in table.columns[1].attrs['th']['class']


def test_table_ordering_attributes_in_meta():
class Table(tables.Table):
alpha = tables.Column()
beta = tables.Column()

class Meta(OrderedTable.Meta):
attrs = {
'th': {
'class': 'custom-header-class-in-meta',
'_ordering': {
'orderable': 'sortable',
'ascending': 'ascend',
'descending': 'descend',
},
}
}

table = Table(MEMORY_DATA)

assert 'sortable' in table.columns[0].attrs['th']['class']
assert 'ascend' in table.columns[0].attrs['th']['class']
assert 'custom-header-class-in-meta' in table.columns[1].attrs['th']['class']


def test_column_ordering_attributes():
class Table(tables.Table):
alpha = tables.Column(attrs={
'th': {
'class': 'custom-header-class',
'_ordering': {
'orderable': 'sort',
'ascending': 'ascending'
}
}
})
beta = tables.Column(attrs={
'th': {
'_ordering': {
'orderable': 'canOrder',
}
},
'td': {
'class': 'cell-2'
}
})

table = Table(MEMORY_DATA, attrs={'class': 'only-on-table'}, order_by='alpha')

assert 'only-on-table' not in table.columns[0].attrs['th']['class']
assert 'custom-header-class' in table.columns[0].attrs['th']['class']
assert 'ascending' in table.columns[0].attrs['th']['class']
assert 'sort' in table.columns[0].attrs['th']['class']
assert 'canOrder' in table.columns[1].attrs['th']['class']


def test_row_attrs():
class Table(tables.Table):
alpha = tables.Column()
Expand Down

0 comments on commit d9ebdfc

Please sign in to comment.