* Added pagination
[django-tables2.git] / tests / core.py
1 """Test the core table functionality."""
2 import copy
3 from attest import Tests, Assert
4 from django.http import Http404
5 from django.core.paginator import Paginator
6 import django_tables as tables
7 from django_tables import utils
8
9 core = Tests()
10
11
12 @core.context
13 def context():
14     class Context(object):
15         memory_data = [
16             {'i': 2, 'alpha': 'b', 'beta': 'b'},
17             {'i': 1, 'alpha': 'a', 'beta': 'c'},
18             {'i': 3, 'alpha': 'c', 'beta': 'a'},
19         ]
20
21         class UnsortedTable(tables.Table):
22             i = tables.Column()
23             alpha = tables.Column()
24             beta = tables.Column()
25
26         table = UnsortedTable(memory_data)
27
28     yield Context
29
30
31 @core.test
32 def declarations(context):
33     """Test defining tables by declaration."""
34     class GeoAreaTable(tables.Table):
35         name = tables.Column()
36         population = tables.Column()
37
38     assert len(GeoAreaTable.base_columns) == 2
39     assert 'name' in GeoAreaTable.base_columns
40     assert not hasattr(GeoAreaTable, 'name')
41
42     class CountryTable(GeoAreaTable):
43         capital = tables.Column()
44
45     assert len(CountryTable.base_columns) == 3
46     assert 'capital' in CountryTable.base_columns
47
48     # multiple inheritance
49     class AddedMixin(tables.Table):
50         added = tables.Column()
51
52     class CityTable(GeoAreaTable, AddedMixin):
53         mayor = tables.Column()
54
55     assert len(CityTable.base_columns) == 4
56     assert 'added' in CityTable.base_columns
57
58
59 @core.test
60 def datasource_untouched(context):
61     """Ensure that data that is provided to the table (the datasource) is not
62     modified by table operations.
63     """
64     original_data = copy.deepcopy(context.memory_data)
65
66     table = context.UnsortedTable(context.memory_data)
67     table.order_by = 'i'
68     list(table.rows)
69     assert context.memory_data == Assert(original_data)
70
71     table = context.UnsortedTable(context.memory_data)
72     table.order_by = 'beta'
73     list(table.rows)
74     assert context.memory_data == Assert(original_data)
75
76
77 @core.test
78 def sorting(context):
79     class MyUnsortedTable(tables.Table):
80         i = tables.Column()
81         alpha = tables.Column()
82         beta = tables.Column()
83
84     # various different ways to say the same thing: don't sort
85     Assert(MyUnsortedTable([]).order_by) == ()
86     Assert(MyUnsortedTable([], order_by=None).order_by) == ()
87     Assert(MyUnsortedTable([], order_by=[]).order_by) == ()
88     Assert(MyUnsortedTable([], order_by=()).order_by) == ()
89
90     # values of order_by are wrapped in tuples before being returned
91     Assert(MyUnsortedTable([], order_by='alpha').order_by) == ('alpha',)
92     Assert(MyUnsortedTable([], order_by=('beta',)).order_by) == ('beta',)
93
94     # a rewritten order_by is also wrapped
95     table = MyUnsortedTable([])
96     table.order_by = 'alpha'
97     assert ('alpha', ) == table.order_by
98
99     # default sort order can be specified in table options
100     class MySortedTable(MyUnsortedTable):
101         class Meta:
102             order_by = 'alpha'
103
104     # order_by is inherited from the options if not explitly set
105     table = MySortedTable([])
106     assert ('alpha',) == table.order_by
107
108     # ...but can be overloaded at __init___
109     table = MySortedTable([], order_by='beta')
110     assert ('beta',) == table.order_by
111
112     # ...or rewritten later
113     table = MySortedTable(context.memory_data)
114     table.order_by = 'beta'
115     assert ('beta',) == table.order_by
116     assert 3 == table.rows[0]['i']
117
118     # ...or reset to None (unsorted), ignoring the table default
119     table = MySortedTable(context.memory_data, order_by=None)
120     assert () == table.order_by
121     assert 2 == table.rows[0]['i']
122
123
124 @core.test
125 def row_subscripting(context):
126     row = context.table.rows[0]
127     # attempt number indexing
128     Assert(row[0]) == 2
129     Assert(row[1]) == 'b'
130     Assert(row[2]) == 'b'
131     with Assert.raises(IndexError) as error:
132         row[3]
133     # attempt column name indexing
134     Assert(row['i']) == 2
135     Assert(row['alpha']) == 'b'
136     Assert(row['beta']) == 'b'
137     with Assert.raises(KeyError) as error:
138         row['gamma']
139
140
141 @core.test
142 def column_count(context):
143     class SimpleTable(tables.Table):
144         visible = tables.Column(visible=True)
145         hidden = tables.Column(visible=False)
146
147     # The columns container supports the len() builtin
148     assert len(SimpleTable([]).columns) == 1
149
150
151 @core.test
152 def column_accessor(context):
153     class SimpleTable(context.UnsortedTable):
154         col1 = tables.Column(accessor='alpha.upper.isupper')
155         col2 = tables.Column(accessor='alpha.upper')
156     table = SimpleTable(context.memory_data)
157     row = table.rows[0]
158     Assert(row['col1']) == True
159     Assert(row['col2']) == 'B'
160
161
162 @core.test
163 def pagination():
164     class BookTable(tables.Table):
165         name = tables.Column()
166
167     # create some sample data
168     data = []
169     for i in range(1,101):
170         data.append({'name': 'Book Nr. %d' % i})
171     books = BookTable(data)
172
173     # external paginator
174     paginator = Paginator(books.rows, 10)
175     assert paginator.num_pages == 10
176     page = paginator.page(1)
177     assert page.has_previous() == False
178     assert page.has_next() == True
179
180     # integrated paginator
181     books.paginate(Paginator, page=1, per_page=10)
182     # rows is now paginated
183     assert len(list(books.rows.page())) == 10
184     assert len(list(books.rows.all())) == 100
185     # new attributes
186     assert books.paginator.num_pages == 10
187     assert books.page.has_previous() == False
188     assert books.page.has_next() == True
189     # exceptions are converted into 404s
190     with Assert.raises(Http404) as error:
191         books.paginate(Paginator, page=9999, per_page=10)
192         books.paginate(Paginator, page='abc', per_page=10)
193
194
195 if __name__ == '__main__':
196     core.main()