How to sort a list of objects in a template in alphabetic order?

perror picture perror · Feb 2, 2014 · Viewed 12.9k times · Source

I want to display a list of objects in a Django generic display view ListView class. And, to make it prettier, I try to sort it in alphabetic order. So, I use the built-in dictsort tag to sort the list.

Here is the summary of the code I used:

{% for item in object_list|dictsort:"name" %}
  ...
{% empty %}
  ...
{% endfor %}

The problem is that it sorts the names according to the ASCII values of the characters, meaning that bigcaps and smallcaps are sorted differently. Here is an example:

Bob
Eve
alice
zoe

And, what I would like to have is the following:

alice
Bob
Eve
zoe

I looked the documentation and several questions in SO, with no success. So, if someone has a way to achieve this, I would be extremely grateful.

Answer

Daniel Roseman picture Daniel Roseman · Feb 2, 2014

You'll need to write a custom filter which sorts by lower case. It's pretty simple:

@register.filter
def sort_lower(lst, key_name):
    return sorted(lst, key=lambda item: getattr(item, key_name).lower())

But if your list is a set of objects from the database, you shouldn't really be sorting them in Python - you should get the database to return them in the order you want.

Edit

How are you using the filter? It should be exactly the same as the dictsort one: object_list|sort_lower:"name".

To sort the queryset in the database, you can use the extra method to add a lower-case version of the field:

MyModel.objects.all().extra(select={'lower_name': 'LOWER(NAME)'}, order_by='lower_name')