Code

Ticket #11868: admin-multisort-1.2-beta-SVN-12755.diff

File admin-multisort-1.2-beta-SVN-12755.diff, 8.5 KB (added by bendavis78, 4 years ago)

Updated for 1.2-beta

Line 
1Index: django/contrib/admin/media/css/base.css
2===================================================================
3--- django/contrib/admin/media/css/base.css     (revision 12755)
4+++ django/contrib/admin/media/css/base.css     (working copy)
5@@ -326,6 +326,20 @@
6     background: url(../img/admin/arrow-up.gif) right .4em no-repeat;
7 }
8 
9+table thead th.sorted a span.text {
10+   display: block;
11+   float: left;
12+}
13+table thead th.sorted a span.sort_pos {
14+   display: block;
15+   float: right;
16+   font-size: .6em;
17+}
18+table thead th.sorted a span.clear{
19+   display: block;
20+   clear: both;
21+}
22+
23 /* ORDERABLE TABLES */
24 
25 table.orderable tbody tr td:hover {
26Index: django/contrib/admin/templatetags/admin_list.py
27===================================================================
28--- django/contrib/admin/templatetags/admin_list.py     (revision 12755)
29+++ django/contrib/admin/templatetags/admin_list.py     (working copy)
30@@ -103,14 +103,44 @@
31 
32         th_classes = []
33         new_order_type = 'asc'
34-        if field_name == cl.order_field or admin_order_field == cl.order_field:
35-            th_classes.append('sorted %sending' % cl.order_type.lower())
36-            new_order_type = {'asc': 'desc', 'desc': 'asc'}[cl.order_type.lower()]
37+        ordering_fields = cl.get_ordering_fields()
38+        sort_pos = ''
39+        if field_name in ordering_fields.keys() or admin_order_field in ordering_fields.keys():
40+            if not field_name in ordering_fields.keys():
41+                field_name = admin_order_field
42+            order_type = ordering_fields.get(field_name).lower()
43+            sort_pos = ordering_fields.keys().index(field_name) + 1
44+            th_classes.append('sorted %sending' % order_type)
45+            new_order_type = {'':'asc', 'asc': 'desc', 'desc': ''}[order_type]
46+       
47+        # build new ordering param
48+        o_list = []
49+        for f in ordering_fields.keys():
50+            try:
51+                n = cl.list_display.index(f)
52+            except ValueError:
53+                continue
54+
55+            if f == field_name:
56+                if new_order_type == '':
57+                    continue
58+                t = new_order_type
59+            else:
60+                t = ordering_fields.get(f)
61 
62+            o_list.append((t=='desc' and '-' or '') + str(n))
63+       
64+        if field_name not in ordering_fields.keys() and new_order_type:
65+            n = cl.list_display.index(field_name)
66+            o_list.append((new_order_type=='desc' and '-' or '') + str(n))
67+
68+        o_list = ','.join(o_list)
69+
70         yield {
71             "text": header,
72             "sortable": True,
73-            "url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
74+            "sort_pos": sort_pos > 0 and len(ordering_fields) > 0 and unicode(sort_pos) or '',
75+            "url": cl.get_query_string({ORDER_VAR: o_list}),
76             "class_attrib": mark_safe(th_classes and ' class="%s"' % ' '.join(th_classes) or '')
77         }
78 
79Index: django/contrib/admin/views/main.py
80===================================================================
81--- django/contrib/admin/views/main.py  (revision 12755)
82+++ django/contrib/admin/views/main.py  (working copy)
83@@ -4,6 +4,7 @@
84 from django.core.paginator import Paginator, InvalidPage
85 from django.db import models
86 from django.db.models.query import QuerySet
87+from django.utils.datastructures import SortedDict
88 from django.utils.encoding import force_unicode, smart_str
89 from django.utils.translation import ugettext
90 from django.utils.http import urlencode
91@@ -63,7 +64,7 @@
92         if ERROR_FLAG in self.params:
93             del self.params[ERROR_FLAG]
94 
95-        self.order_field, self.order_type = self.get_ordering()
96+        self.ordering = self.get_ordering()
97         self.query = request.GET.get(SEARCH_VAR, '')
98         self.query_set = self.get_query_set()
99         self.get_results(request)
100@@ -137,37 +138,48 @@
101         # those exist, order descending by ID by default. Finally, look for
102         # manually-specified ordering from the query string.
103         ordering = self.model_admin.ordering or lookup_opts.ordering or ['-' + lookup_opts.pk.name]
104-
105-        if ordering[0].startswith('-'):
106-            order_field, order_type = ordering[0][1:], 'desc'
107-        else:
108-            order_field, order_type = ordering[0], 'asc'
109+       
110         if ORDER_VAR in params:
111-            try:
112-                field_name = self.list_display[int(params[ORDER_VAR])]
113+            # Clear ordering and used params
114+            ordering = []
115+            order_params = params[ORDER_VAR].split(',')
116+            for p in order_params:
117                 try:
118-                    f = lookup_opts.get_field(field_name)
119-                except models.FieldDoesNotExist:
120-                    # See whether field_name is a name of a non-field
121-                    # that allows sorting.
122+                    none, pfx, idx = p.rpartition('-')
123+                    field_name = self.list_display[int(idx)]
124                     try:
125-                        if callable(field_name):
126-                            attr = field_name
127-                        elif hasattr(self.model_admin, field_name):
128-                            attr = getattr(self.model_admin, field_name)
129-                        else:
130-                            attr = getattr(self.model, field_name)
131-                        order_field = attr.admin_order_field
132-                    except AttributeError:
133-                        pass
134-                else:
135-                    order_field = f.name
136-            except (IndexError, ValueError):
137-                pass # Invalid ordering specified. Just use the default.
138-        if ORDER_TYPE_VAR in params and params[ORDER_TYPE_VAR] in ('asc', 'desc'):
139-            order_type = params[ORDER_TYPE_VAR]
140-        return order_field, order_type
141+                        f = lookup_opts.get_field(field_name)
142+                    except models.FieldDoesNotExist:
143+                        # See whether field_name is a name of a non-field
144+                        # that allows sorting.
145+                        try:
146+                            if callable(field_name):
147+                                attr = field_name
148+                            elif hasattr(self.model_admin, field_name):
149+                                attr = getattr(self.model_admin, field_name)
150+                            else:
151+                                attr = getattr(self.model, field_name)
152+                            field_name = attr.admin_order_field
153+                        except AttributeError:
154+                            pass
155+                    else:
156+                        field_name = f.name
157 
158+                    ordering.append(pfx + field_name)
159+
160+                except (IndexError, ValueError):
161+                    pass # Invalid ordering specified. Skip it.
162+
163+        return ordering
164+   
165+    def get_ordering_fields(self):
166+        # Returns a SortedDict of ordering fields and asc/desc
167+        ordering_fields = SortedDict()
168+        for o in self.ordering:
169+            none, t, f = o.rpartition('-')
170+            ordering_fields[f] = t == '-' and 'desc' or 'asc'
171+        return ordering_fields
172+
173     def get_query_set(self):
174         qs = self.root_query_set
175         lookup_params = self.params.copy() # a dictionary of the query string
176@@ -214,8 +226,8 @@
177                             break
178 
179         # Set ordering.
180-        if self.order_field:
181-            qs = qs.order_by('%s%s' % ((self.order_type == 'desc' and '-' or ''), self.order_field))
182+        if self.ordering:
183+            qs = qs.order_by(*self.ordering)
184 
185         # Apply keyword searches.
186         def construct_search(field_name):
187Index: django/contrib/admin/templates/admin/change_list_results.html
188===================================================================
189--- django/contrib/admin/templates/admin/change_list_results.html       (revision 12755)
190+++ django/contrib/admin/templates/admin/change_list_results.html       (working copy)
191@@ -2,10 +2,14 @@
192 <table cellspacing="0">
193 <thead>
194 <tr>
195-{% for header in result_headers %}<th{{ header.class_attrib }}>
196-{% if header.sortable %}<a href="{{ header.url }}">{% endif %}
197-{{ header.text|capfirst }}
198-{% if header.sortable %}</a>{% endif %}</th>{% endfor %}
199+{% for header in result_headers %}
200+<th{{ header.class_attrib }}>
201+  {% if header.sortable %}<a href="{{ header.url }}">{% endif %}
202+  <span class="text">{{ header.text|capfirst }}</span>
203+  {% if header.sortable %}<span class="sort_pos">{{ header.sort_pos }}</span>
204+  <span class="clear"></span>
205+  </a>{% endif %}
206+</th>{% endfor %}
207 </tr>
208 </thead>
209 <tbody>