1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108 | ORDER_VAR = 'o'
ORDER_TYPE_VAR = 'ot'
class SortHeaders:
"""
Handles generation of an argument for the Django ORM's
``order_by`` method and generation of table headers which reflect
the currently selected sort, based on defined table headers with
matching sort criteria.
Based in part on the Django Admin application's ``ChangeList``
functionality.
"""
def __init__(self, request, headers, default_order_field=None,
default_order_type='asc', additional_params=None):
"""
request
The request currently being processed - the current sort
order field and type are determined based on GET
parameters.
headers
A list of two-tuples of header text and matching ordering
criteria for use with the Django ORM's ``order_by``
method. A criterion of ``None`` indicates that a header
is not sortable.
default_order_field
The index of the header definition to be used for default
ordering and when an invalid or non-sortable header is
specified in GET parameters. If not specified, the index
of the first sortable header will be used.
default_order_type
The default type of ordering used - must be one of
``'asc`` or ``'desc'``.
additional_params:
Query parameters which should always appear in sort links,
specified as a dictionary mapping parameter names to
values. For example, this might contain the current page
number if you're sorting a paginated list of items.
"""
if default_order_field is None:
for i, (header, query_lookup) in enumerate(headers):
if query_lookup is not None:
default_order_field = i
break
if default_order_field is None:
raise AttributeError('No default_order_field was specified and none of the header definitions given were sortable.')
if default_order_type not in ('asc', 'desc'):
raise AttributeError('If given, default_order_type must be one of \'asc\' or \'desc\'.')
if additional_params is None: additional_params = {}
self.header_defs = headers
self.additional_params = additional_params
self.order_field, self.order_type = default_order_field, default_order_type
# Determine order field and order type for the current request
params = dict(request.GET.items())
if ORDER_VAR in params:
try:
new_order_field = int(params[ORDER_VAR])
if headers[new_order_field][1] is not None:
self.order_field = new_order_field
except (IndexError, ValueError):
pass # Use the default
if ORDER_TYPE_VAR in params and params[ORDER_TYPE_VAR] in ('asc', 'desc'):
self.order_type = params[ORDER_TYPE_VAR]
def headers(self):
"""
Generates dicts containing header and sort link details for
all defined headers.
"""
for i, (header, order_criterion) in enumerate(self.header_defs):
th_classes = []
new_order_type = 'asc'
if i == self.order_field:
th_classes.append('sorted %sending' % self.order_type)
new_order_type = {'asc': 'desc', 'desc': 'asc'}[self.order_type]
yield {
'text': header,
'sortable': order_criterion is not None,
'url': self.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
'class_attr': (th_classes and ' class="%s"' % ' '.join(th_classes) or ''),
}
def get_query_string(self, params):
"""
Creates a query string from the given dictionary of
parameters, including any additonal parameters which should
always be present.
"""
params.update(self.additional_params)
return '?%s' % '&'.join(['%s=%s' % (param, value) \
for param, value in params.items()])
def get_order_by(self):
"""
Creates an ordering criterion based on the current order
field and order type, for use with the Django ORM's
``order_by`` method.
"""
return '%s%s' % (
self.order_type == 'desc' and '-' or '',
self.header_defs[self.order_field][1],
)
|
Comments
line 66: except (IndexError, ValueError) instead of IndexError, ValueError
great work!
#
Whoops, thanks for pointing that out - fixed it now.
#
Would it be possible to use ordering criteria that span relationships?
Lets say I have article model and each article belogs to a user.
I would like to order the artcles by user email
but I get an error when I add ('Email Address', 'user__email') to LIST_HEADERS.
Best,
Sebastian Macias
#
I'm affraid there would be a problem when using pagination.
Do you have pagination enabled version of sorted headers list ?
Thanks
#
Nice work! Thanks a lot.
#
This actually works quite well with the Paginator.
Just follow the example on: http://docs.djangoproject.com/en/dev/topics/pagination/
And change in your for loop:
{% for user in users %} to {% for user in users.object_list %}
That worked for me anyways...
#
A possible alternative is to use pure Javascript table sort:
http://www.kryogenix.org/code/browser/sorttable/
#
Is there anyway to independently sort multiple tables on a single page?
#
I'm using this code with django 1.2.5 and I get the following error in a simple list view:
Line 60 of sort_headers.py is this line:
In the debug output, the request object is a generator object when this method is called. Has anyone else seen this? Thanks.
#
I figured out my problem. It was unrelated to this code.
#
I had a search form in the list page with the method get. I had to add some extra lines to include the request get query string in the sorted link path. enjoy
[HTML_REMOVED]
#
if ORDER_TYPE_VAR in params and params[ORDER_TYPE_VAR] in ('asc', 'desc'): self.order_type = params[ORDER_TYPE_VAR]
#
Perancis adalah negara maju, [7] dan memiliki ekonomi terbesar kedua di Eropa terbesar kelima di dunia dengan PDB nominal. Itu juga merupakan tips cepat hamil dunia terbesar kesembilan dengan PDB paritas soal ulangan harian sd daya beli [8] Perancis adalah negara terkaya di Eropa -. Dan keempat terkaya di dunia -. Dalam kekayaan rumah tangga agregat [9] teknisi komputer warga Perancis menikmati standar tinggi hidup, tingkat pendidikan publik yang tinggi, dan salah satu harapan hidup terpanjang di click here dunia. [10] Perancis telah terdaftar sebagai "perawatan kesehatan secara keseluruhan terbaik" penyedia dunia oleh Organisasi kursus bahasa inggris Kesehatan dunia. [11] ini adalah negara yang paling dikunjungi di dunia, menerima 79.500.000 turis mendapatkan uang dari internet asing per tahun [12].
#