There are times when a Char field can have number and alpha values and you want them sorted such that the numbers come out in numeric rather than alphanumeric order followed by the text values.
For example, academic course sections may be named 1, 2, 14, A, B, C, and so on (not my decision, I should add.) So we have
class Section(models.Model): name = models.CharField(maxlength=3) schedule_course = models.ForeignKey(ScheduleCourse) instructors = models.ManyToManyField(Contact) ...
When we list the sections we want to see something like:
2 LEC: W 6:30pm-9:20pm 14 LEC: Th 6:30pm-9:20pm A LEC: M W F 10:00am-10:50am B LEC: M W F 11:00am-11:50am
rather than the alphanumerically ordered:
14 LEC: Th 6:30pm-9:20pm 2 LEC: W 6:30pm-9:20pm A LEC: M W F 10:00am-10:50am B LEC: M W F 11:00am-11:50am
We accomplish this with a template filter as in {% for section in sc.section_set.all|sorted_int_then_alpha:"name" %
}.
The code for sorted_int_then_alpha
follows:
from django import template from itertools import chain from operator import attrgetter register = template.Library() @register.filter def sorted_int_then_alpha(items, attr): """ Return items sorted on attr where int values come first and in numerical order followed by anything else in aplhanumeric ordering """ key = attrgetter(attr) sorted_ints = sorted([(int(key(item)),item) for item in items if key(item).isdigit()]) sorted_strs = sorted([(key(item),item) for item in items if not key(item).isdigit()]) return [item for (_sorter, item) in chain(sorted_ints, sorted_strs)]