djangosortingdjango-queryset

Sort by display name instead of actual value


Consider this sample model:

MODEL_CHOICES = ( (u"SPAM", u"Spam"), (u"XOUP", u"Eggsoup"), )

(snip)

type = models.CharField(max_length=4, choices=MODEL_CHOICES)

(The actual implementation is domain-specific and in non-English, so this sample has to do.)

When building my query, I'd like to sort the results by that type field, and present the results to the user. Naturally, I'd like to sort by the display name of that field.

Something along the lines of:

documents = MyModel.objects.filter(...).order_by("type")

However, [query-set].order_by([field]) only allows sorting by field name, which will result in SPAM < XOUP (to the machine) even though Eggsoup < Spam (to the human reader).

Consider this set of instances sorted by type:

Name | Type

obj1 | SPAM

obj2 | SPAM

obj3 | SPAM

obj4 | XOUP

obj5 | XOUP

But this is the order the user will see, i.e. the user will see the display name, not the internal field value of the type column:

Name | Type

obj1 | Spam

obj2 | Spam

obj3 | Spam

obj4 | Eggsoup

obj5 | Eggsoup

Which in the eyes of the human user is not sorted correctly.

Is there a feature in Django that allows sorting by display name? Or a way to accomplish this "manually"? (Renaming the choices so that the display name has the same order as the actual values is not an option.)


Solution

  • If the result sets are small enough, you could do an in-memory sort of results in code. I can't think of any decent way to sort the results in database level. It certainly would be possible if you used stored procedure which is aware of display names, however you'd have to write raw sql. As for manual sorting- you can use something like this:

    obj_list = list(Model.objects.all())
    import operator
    obj_list.sort(key=operator.methodcaller('get_foo_display'))
    

    Here are some nice examples on how to sort lists in Python: http://wiki.python.org/moin/HowTo/Sorting