Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #3397: You can now order by non-DB fields in the admin by telli…

…ng Django which field to actually order by. Thanks, marcink@elksoft.pl

git-svn-id: http://code.djangoproject.com/svn/django/trunk@4596 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit abf79841fe6cce5f1f66f915815ed98ecca44e64 1 parent 3d164ab
@jacobian jacobian authored
View
31 django/contrib/admin/templatetags/admin_list.py
@@ -84,22 +84,31 @@ def result_headers(cl):
header = attr.short_description
except AttributeError:
header = field_name.replace('_', ' ')
- # Non-field list_display values don't get ordering capability.
- yield {"text": header}
+
+ # It is a non-field, but perhaps one that is sortable
+ if not getattr(getattr(cl.model, field_name), "admin_order_field", None):
+ yield {"text": header}
+ continue
+
+ # So this _is_ a sortable non-field. Go to the yield
+ # after the else clause.
else:
if isinstance(f.rel, models.ManyToOneRel) and f.null:
yield {"text": f.verbose_name}
+ continue
else:
- th_classes = []
- new_order_type = 'asc'
- if field_name == cl.order_field:
- th_classes.append('sorted %sending' % cl.order_type.lower())
- new_order_type = {'asc': 'desc', 'desc': 'asc'}[cl.order_type.lower()]
+ header = f.verbose_name
+
+ th_classes = []
+ new_order_type = 'asc'
+ if field_name == cl.order_field:
+ th_classes.append('sorted %sending' % cl.order_type.lower())
+ new_order_type = {'asc': 'desc', 'desc': 'asc'}[cl.order_type.lower()]
- yield {"text": f.verbose_name,
- "sortable": True,
- "url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
- "class_attrib": (th_classes and ' class="%s"' % ' '.join(th_classes) or '')}
+ yield {"text": header,
+ "sortable": True,
+ "url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
+ "class_attrib": (th_classes and ' class="%s"' % ' '.join(th_classes) or '')}
def _boolean_icon(field_val):
BOOLEAN_MAPPING = {True: 'yes', False: 'no', None: 'unknown'}
View
11 django/contrib/admin/views/main.py
@@ -655,10 +655,17 @@ def get_ordering(self):
order_field, order_type = ordering[0], 'asc'
if params.has_key(ORDER_VAR):
try:
+ field_name = lookup_opts.admin.list_display[int(params[ORDER_VAR])]
try:
- f = lookup_opts.get_field(lookup_opts.admin.list_display[int(params[ORDER_VAR])])
+ f = lookup_opts.get_field(field_name)
except models.FieldDoesNotExist:
- pass
+ # see if field_name is a name of a non-field
+ # that allows sorting
+ try:
+ attr = getattr(lookup_opts.admin.manager.model, field_name)
+ order_field = attr.admin_order_field
+ except IndexError:
+ pass
else:
if not isinstance(f.rel, models.ManyToOneRel) or not f.null:
order_field = f.name
View
28 docs/model-api.txt
@@ -1295,10 +1295,30 @@ A few special cases to note about ``list_display``:
list_display = ('__str__', 'some_other_field')
- * For any element of ``list_display`` that is not a field on the model, the
- change list page will not allow ordering by that column. This is because
- ordering is done at the database level, and Django has no way of knowing
- how to order the result of a custom method at the SQL level.
+ * Usually, elements of ``list_display`` that aren't actual database fields
+ can't be used in sorting (because Django does all the sorting at the
+ database level).
+
+ However, if an element of ``list_display`` represents a certain database
+ field, you can indicate this fact by setting the ``admin_order_field``
+ attribute of the item.
+
+ For example::
+
+ class Person(models.Model):
+ first_name = models.CharField(maxlength=50)
+ color_code = models.CharField(maxlength=6)
+
+ class Admin:
+ list_display = ('first_name', 'colored_first_name')
+
+ def colored_first_name(self):
+ return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
+ colored_first_name.allow_tags = True
+ colored_first_name.admin_order_field = 'first_name'
+
+ The above will tell Django to order by the ``first_name`` field when
+ trying to sort by ``colored_first_name`` in the admin.
``list_display_links``
----------------------
Please sign in to comment.
Something went wrong with that request. Please try again.