From 74e129bea54988a1ce6735df77206ae5647c3d11 Mon Sep 17 00:00:00 2001 From: Michael Elsdoerfer Date: Sun, 29 Jun 2008 15:13:30 +0200 Subject: [PATCH] standard tables now support an inner metaclass; the new 'sortable' option allows setting a table-wide default --- README | 15 +++++++++++++++ django_tables/columns.py | 2 +- django_tables/models.py | 5 +++-- django_tables/tables.py | 18 ++++++++++++++++-- tests/test_basic.py | 26 ++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 5 deletions(-) diff --git a/README b/README index 4467b37..71ae096 100644 --- a/README +++ b/README @@ -122,6 +122,21 @@ the row instance as an argument (representing the row that the default is needed for). +Table Options +------------- + +Table-specific options are implemented using the same inner ``Meta`` class +concept as known from forms and models in Django: + + class MyTable(tables.Table): + class Meta: + sortable = True + +Currently, for non-model tables, the only supported option is ``sortable``. +Per default, all columns are sortable, unless a column specifies otherwise. +This meta option allows you to overwrite the global default for the table. + + ModelTables ----------- diff --git a/django_tables/columns.py b/django_tables/columns.py index 51e71b1..b715f14 100644 --- a/django_tables/columns.py +++ b/django_tables/columns.py @@ -41,7 +41,7 @@ class Column(object): creation_counter = 0 def __init__(self, verbose_name=None, name=None, default=None, data=None, - visible=True, inaccessible=False, sortable=True): + visible=True, inaccessible=False, sortable=None): self.verbose_name = verbose_name self.name = name self.default = default diff --git a/django_tables/models.py b/django_tables/models.py index 9aea735..3f4e794 100644 --- a/django_tables/models.py +++ b/django_tables/models.py @@ -1,12 +1,13 @@ from django.core.exceptions import FieldError from django.utils.datastructures import SortedDict from tables import BaseTable, DeclarativeColumnsMetaclass, \ - Column, BoundRow, Rows + Column, BoundRow, Rows, TableOptions __all__ = ('BaseModelTable', 'ModelTable') -class ModelTableOptions(object): +class ModelTableOptions(TableOptions): def __init__(self, options=None): + super(ModelTableOptions, self).__init__() self.model = getattr(options, 'model', None) self.columns = getattr(options, 'columns', None) self.exclude = getattr(options, 'exclude', None) diff --git a/django_tables/tables.py b/django_tables/tables.py index 7a284a0..56a9e33 100644 --- a/django_tables/tables.py +++ b/django_tables/tables.py @@ -28,6 +28,11 @@ def sort_table(data, order_by): instructions.append((o, False,)) data.sort(cmp=_cmp) +class TableOptions(object): + def __init__(self, options=None): + super(TableOptions, self).__init__() + self.sortable = getattr(options, 'sortable', None) + class DeclarativeColumnsMetaclass(type): """ Metaclass that converts Column attributes to a dictionary called @@ -83,6 +88,7 @@ class DeclarativeColumnsMetaclass(type): attrs['base_columns'] = SortedDict() attrs['base_columns'].update(SortedDict(columns)) + attrs['_meta'] = TableOptions(attrs.get('Meta', None)) return type.__new__(cls, name, bases, attrs) def rmprefix(s): @@ -298,7 +304,7 @@ class BaseTable(object): """ if purpose == 'order_by': return name in self.columns and\ - self.columns[name].column.sortable + self.columns[name].sortable else: return True @@ -471,9 +477,17 @@ class BoundColumn(StrAndUnicode): self.column = column self.declared_name = name # expose some attributes of the column more directly - self.sortable = column.sortable self.visible = column.visible + def _get_sortable(self): + if self.column.sortable is not None: + return self.column.sortable + elif self.table._meta.sortable is not None: + return self.table._meta.sortable + else: + return True # the default value + sortable = property(_get_sortable) + name = property(lambda s: s.column.name or s.declared_name) name_reversed = property(lambda s: "-"+s.name) def _get_name_toggled(self): diff --git a/tests/test_basic.py b/tests/test_basic.py index 589bbfc..48c67a3 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -126,6 +126,32 @@ def test_caches(): assert id(list(books.columns)[0]) != old_column_cache assert id(list(books.rows)[0]) != old_row_cache +def test_meta_sortable(): + """Specific tests for sortable table meta option.""" + + def mktable(default_sortable): + class BookTable(tables.Table): + id = tables.Column(sortable=True) + name = tables.Column(sortable=False) + author = tables.Column() + class Meta: + sortable = default_sortable + return BookTable([]) + + global_table = mktable(None) + for default_sortable, results in ( + (None, (True, False, True)), # last bool is global default + (True, (True, False, True)), # last bool is table default + (False, (True, False, False)), # last bool is table default + ): + books = mktable(default_sortable) + assert [c.sortable for c in books.columns] == list(results) + + # it also works if the meta option is manually changed after + # class and instance creation + global_table._meta.sortable = default_sortable + assert [c.sortable for c in global_table.columns] == list(results) + def test_sort(): class BookTable(tables.Table): id = tables.Column() -- 2.26.2