Skip to content

Commit 5047081

Browse files
adammckmiracle2k
authored andcommitted
added default 'order_by' option to tables.
this allows tables to specify a default sort order, which includes all of the UI of an explicitly-sorted dataset. also, some tests. they fail for BaseTable, because sorting doesn't seem to be implemented there. it should be, though, despite being crazy.
1 parent 5ee0080 commit 5047081

File tree

3 files changed

+91
-4
lines changed

3 files changed

+91
-4
lines changed

django_tables/base.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class TableOptions(object):
1515
def __init__(self, options=None):
1616
super(TableOptions, self).__init__()
1717
self.sortable = getattr(options, 'sortable', None)
18+
self.order_by = getattr(options, 'order_by', None)
1819

1920

2021
class DeclarativeColumnsMetaclass(type):
@@ -419,10 +420,16 @@ class BaseTable(object):
419420

420421
rows_class = Rows
421422

422-
def __init__(self, data, order_by=None):
423+
# this value is not the same as None. it means 'use the default sort
424+
# order', which may (or may not) be inherited from the table options.
425+
# None means 'do not sort the data', ignoring the default.
426+
DefaultOrder = type('DefaultSortType', (), {})()
427+
428+
def __init__(self, data, order_by=DefaultOrder):
423429
"""Create a new table instance with the iterable ``data``.
424430
425431
If ``order_by`` is specified, the data will be sorted accordingly.
432+
Otherwise, the sort order can be specified in the table options.
426433
427434
Note that unlike a ``Form``, tables are always bound to data. Also
428435
unlike a form, the ``columns`` attribute is read-only and returns
@@ -439,7 +446,14 @@ def __init__(self, data, order_by=None):
439446
self._rows = self.rows_class(self)
440447
self._columns = Columns(self)
441448

442-
self.order_by = order_by
449+
# None is a valid order, so we must use DefaultOrder as a flag
450+
# to fall back to the table sort order. set the attr via the
451+
# property, to wrap it in an OrderByTuple before being stored
452+
if order_by != BaseTable.DefaultOrder:
453+
self.order_by = order_by
454+
455+
else:
456+
self.order_by = self._meta.order_by
443457

444458
# Make a copy so that modifying this will not touch the class
445459
# definition. Note that this is different from forms, where the
@@ -545,6 +559,7 @@ def _set_order_by(self, value):
545559
self._order_by = OrderByTuple(validated_order_by)
546560
else:
547561
self._order_by = OrderByTuple()
562+
548563
order_by = property(lambda s: s._order_by, _set_order_by)
549564

550565
def __unicode__(self):

tests/test_basic.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"""
33

44

5-
from nose.tools import assert_raises
5+
from nose.tools import assert_raises, assert_equal
66
from django.http import Http404
77
from django.core.paginator import Paginator
88
import django_tables as tables
@@ -53,6 +53,64 @@ class StateTable2(GeoAreaTable, tables.ModelTable):
5353
assert 'motto' in StateTable2.base_columns
5454

5555

56+
def test_sort():
57+
class MyUnsortedTable(TestTable):
58+
alpha = tables.Column()
59+
beta = tables.Column()
60+
n = tables.Column()
61+
62+
test_data = [
63+
{'alpha': "mmm", 'beta': "mmm", 'n': 1 },
64+
{'alpha': "aaa", 'beta': "zzz", 'n': 2 },
65+
{'alpha': "zzz", 'beta': "aaa", 'n': 3 }]
66+
67+
# unsorted (default) preserves order
68+
assert_equal(1, MyUnsortedTable(test_data ).rows[0]['n'])
69+
assert_equal(1, MyUnsortedTable(test_data, order_by=None).rows[0]['n'])
70+
assert_equal(1, MyUnsortedTable(test_data, order_by=[] ).rows[0]['n'])
71+
assert_equal(1, MyUnsortedTable(test_data, order_by=() ).rows[0]['n'])
72+
73+
# values of order_by are wrapped in tuples before being returned
74+
assert_equal(('alpha',), MyUnsortedTable([], order_by='alpha').order_by)
75+
assert_equal(('beta',), MyUnsortedTable([], order_by=('beta',)).order_by)
76+
assert_equal((), MyUnsortedTable([]).order_by)
77+
78+
# a rewritten order_by is also wrapped
79+
table = MyUnsortedTable([])
80+
table.order_by = 'alpha'
81+
assert_equal(('alpha',), table.order_by)
82+
83+
# data can be sorted by any column
84+
assert_equal(2, MyUnsortedTable(test_data, order_by='alpha').rows[0]['n'])
85+
assert_equal(3, MyUnsortedTable(test_data, order_by='beta' ).rows[0]['n'])
86+
87+
# default sort order can be specified in table options
88+
class MySortedTable(MyUnsortedTable):
89+
class Meta:
90+
order_by = 'alpha'
91+
92+
# order_by is inherited from the options if not explitly set
93+
table = MySortedTable(test_data)
94+
assert_equal(('alpha',), table.order_by)
95+
assert_equal(2, table.rows[0]['n'])
96+
97+
# ...but can be overloaded at __init___
98+
table = MySortedTable(test_data, order_by='beta')
99+
assert_equal(('beta',), table.order_by)
100+
assert_equal(3, table.rows[0]['n'])
101+
102+
# ...or rewritten later
103+
table = MySortedTable(test_data)
104+
table.order_by = 'beta'
105+
assert_equal(('beta',), table.order_by)
106+
assert_equal(3, table.rows[0]['n'])
107+
108+
# ...or reset to None (unsorted), ignoring the table default
109+
table = MySortedTable(test_data, order_by=None)
110+
assert_equal((), table.order_by)
111+
assert_equal(1, table.rows[0]['n'])
112+
113+
56114
def test_column_count():
57115
class MyTable(TestTable):
58116
visbible = tables.Column(visible=True)

tests/test_models.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Sets up a temporary Django project using a memory SQLite database.
44
"""
55

6-
from nose.tools import assert_raises
6+
from nose.tools import assert_raises, assert_equal
77
from django.conf import settings
88
from django.core.paginator import *
99
import django_tables as tables
@@ -206,6 +206,20 @@ class Meta:
206206
countries.order_by = ('custom1', 'custom2')
207207
assert countries.order_by == ()
208208

209+
def test_default_sort():
210+
class SortedCountryTable(tables.ModelTable):
211+
class Meta:
212+
model = Country
213+
order_by = '-name'
214+
215+
# the default order can be inherited from the table
216+
assert_equal(('-name',), SortedCountryTable().order_by)
217+
assert_equal(4, SortedCountryTable().rows[0]['id'])
218+
219+
# and explicitly set (or reset) via __init__
220+
assert_equal(2, SortedCountryTable(order_by='system').rows[0]['id'])
221+
assert_equal(1, SortedCountryTable(order_by=None).rows[0]['id'])
222+
209223
def test_callable():
210224
"""Some of the callable code is reimplemented for modeltables, so
211225
test some specifics again.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy