diff --git a/horizon/tables/base.py b/horizon/tables/base.py index eb34512589..b6c3dbe2b1 100644 --- a/horizon/tables/base.py +++ b/horizon/tables/base.py @@ -347,7 +347,14 @@ class Column(html.HTMLElement): data = display_value[0] else: for filter_func in self.filters: - data = filter_func(data) + try: + data = filter_func(data) + except Exception: + msg = ("Filter '%(filter)s' failed with data " + "'%(data)s' on column '%(col_name)s'") + LOG.warning(msg, {'filter': filter_func.func_name, + 'data': data, + 'col_name': unicode(self.verbose_name)}) if data and self.truncate: data = truncatechars(data, self.truncate) diff --git a/horizon/test/tests/tables.py b/horizon/test/tests/tables.py index 64bba3d52f..e0f59eefd9 100644 --- a/horizon/test/tests/tables.py +++ b/horizon/test/tests/tables.py @@ -18,6 +18,7 @@ from django.core.urlresolvers import reverse from django import forms from django import http from django import shortcuts +from django.template import defaultfilters from mox import IsA # noqa @@ -1091,6 +1092,19 @@ class DataTableTests(test.TestCase): row = self.table.get_rows()[0] self.assertTrue("down" in row.cells['status'].value) + def test_broken_filter(self): + class MyTableBrokenFilter(MyTable): + value = tables.Column('value', + filters=(defaultfilters.timesince,)) + + value = "not_a_date" + data = TEST_DATA[0] + data.value = value + + table = MyTableBrokenFilter(self.request, [data]) + resp = http.HttpResponse(table.render()) + self.assertContains(resp, value) + class SingleTableView(table_views.DataTableView): table_class = MyTable