Wessi
Wessi

Reputation: 1802

Django reverse ordering with ListView

I have implemented ordering in a generic ListView:

class CarList(LoginRequiredMixin, ListView):
    model = Car
    paginate_by = 30

    ordering = 'car_id_internal'

    def get_ordering(self):
        return self.request.GET.get('ordering', 'car_id_internal')

    def get_context_data(self, *args, **kwargs):
        context = super(CarList, self).get_context_data(*args, **kwargs)
        context['current_order'] = self.get_ordering()
        return context

And in my template:

<thead>
    <tr>
        <th><a href="{% url 'car_list' %}?ordering=car_id_internal">Internal car ID</a></th>
        <th><a href="{% url 'car_list' %}?ordering=type">Type</a></th>
        <th><a href="{% url 'car_list' %}?ordering=brand">Brand</a></th>
    </tr>
</thead>

This works fine, however I would like for user to be able to reverse the order from ascending to descending when they click on the column header again. Is that possible with Django? I'm using Django 1.9.

I hope someone can help.

Upvotes: 3

Views: 3245

Answers (1)

NS0
NS0

Reputation: 6096

You need to use another variable for determining the asc/desc ordering. Depending on which is currently selected the template should alternate the links. In the view, you reverse the ordering by adding a dash before the field's name. Try the following:

class CarList(ListView):
    model = Car
    paginate_by = 30

    ordering = 'car_id_internal'
    def get_ordering(self):
        self.order = self.request.GET.get('order', 'asc')
        selected_ordering = self.request.GET.get('ordering', 'car_id_internal')
        if self.order == "desc":
            selected_ordering = "-" + selected_ordering
        return selected_ordering

    def get_context_data(self, *args, **kwargs):
        context = super(CarList, self).get_context_data(*args, **kwargs)
        context['current_order'] = self.get_ordering()
        context['order'] = self.order
        return context

And the template:

<table>
<tr>
    <th><a href="{% url 'car_list' %}?ordering=car_id_internal&order={% if order == 'desc' %}asc{% else %}desc{% endif %}">Internal car ID</a></th>
    <th><a href="{% url 'car_list' %}?ordering=type&order={% if order == 'desc' %}asc{% else %}desc{% endif %}">Type</a></th>
    <th><a href="{% url 'car_list' %}?ordering=brand&order={% if order == 'desc' %}asc{% else %}desc{% endif %}">Brand</a></th>
</tr>
{% for car in object_list %}
<tr>
    <td>{{car.id}}</td>
    <td>{{car.type}}</td>
    <td>{{car.brand}}</td>
</tr>
{% endfor %}

Upvotes: 6

Related Questions