Question

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.)

Was it helpful?

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

OTHER TIPS

Assuming the display name comes from the model as well then you can sort by that field to order the choices like you want.

MODEL_CHOICES = MyModel.objects.all().values_list('value_field', 'display_field').order_by('display_field')
...
type = models.CharField(max_length=4, choices=MODEL_CHOICES)

If the choices are a constant like in your question then you can simply change the order in the constant.

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

In the end the choices is just a list of tuples so you can sort with normal Python sort. The Python wiki has a nice example of sorting a list of tuples on the second element.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top