[Django]-Sortable table columns in django

16👍

57👍

If you use pagination rather than a Javascript table sorter, it might not be sufficient or behave unexpected.


Create every column header as a link e.g.

<th><a href="?order_by=name">Name</a></th>

and in your view you check whether the order_by parameter is set or not:

order_by = request.GET.get('order_by', 'defaultOrderField')
Model.objects.all().order_by(order_by)

11👍

I used the approach followed by the most voted answer above. But I solve the ascending/descending ordering when clicking multiple times on the column header by using a custom tag.

The tag:

from urllib.parse import urlencode
from collections import OrderedDict

@register.simple_tag
def url_replace(request, field, value, direction=''):
    dict_ = request.GET.copy()

    if field == 'order_by' and field in dict_.keys():          
      if dict_[field].startswith('-') and dict_[field].lstrip('-') == value:
        dict_[field] = value
      elif dict_[field].lstrip('-') == value:
        dict_[field] = "-" + value
      else:
        dict_[field] = direction + value
    else:
      dict_[field] = direction + value

    return urlencode(OrderedDict(sorted(dict_.items())))

Then you use this tag on your column header, like above:

<th><a href="?{% url_replace request 'order_by' 'name' '-' %}">Name</a></th>

First time you click it will sort in ‘descending’ order, if you click the same header again it will revert to ‘ascending’ order.

This approach also preserves other parameters in your URL, like page number if you are using a paginator. It requires no extra libraries. Only thing you need to make sure is that your view is sending the RequestContext to the template.

👤mpaf

10👍

I suggest you have a look at django-tables2. It’s designed to solve your exact problem. The documentation has a bunch of examples.

1👍

continuing on the most voted answer above by Felix Kling and the addition by mpaf and ngeek, when using class based views:
do the sorting in the get_queryset(self) method, and use:

<th><a href="?{% url_replace view.request 'order_by' 'name' '-' %}">Name</a></th>

instead of just request in your template

👤Sara

Leave a comment