Django: How to write query to sort using multiple columns, display via template

pete picture pete · Nov 28, 2013 · Viewed 37.8k times · Source

I'm quite new to Django, and not too experienced with MVC, DB queries.

I have a Customer table which includes customer_name, city_name, as well as a state_name (pulled from a foreign key table). In the HTML, I'm trying to display the results in a list first sorted alphabetically by state_name, then by city_name, then by customer_name name. Like so..

ARIZONA
   PHOENIX
     AAA, Inc.
     BBB, LLC.

   SCOTTSDALE
     AAA, LLC.
     DDD, Corp.

CALIFORNIA
   ANAHEIM
     ...

My model.py is as follows:

from django.db import models

class Customer(models.Model):
    def __unicode__(self):
        return self.customer_name

    customer_name = models.CharField(max_length=60)
    city_name = models.CharField(max_length=30)
    state = models.ForeignKey('State')

class State(models.Model):
    def __unicode__(self):
         return self.state_name

    state_name = models.CharField(max_length=20)
    state_code = models.CharField(max_length=2)

In my urls.py, I have:

url("^customers/$",
    direct_to_template,
    {'template': 'pages_fixed/customers.html',
    'extra_context': {'customers': Customer.objects.all().order_by('state')}},
    name='customers'),

And in my HTML, I have a working template as:

    <div class='customers'>
        {% for customer in customers %}
            <div class='block_customer'>
                <p>{{ customer.state.state_name }}</p>
                <p>{{ customer.city_name }}</p>
                <p>{{ customer.customer_name }}</p>
            </div>
        {% endfor %}
    </div>

It's all sort of working but obviously not sorting correctly and I'm not sure what's the best way to design it. I tried some inner loops with the templates, was hoping the templates would let me define some sorting rules but this doesn't seem to be supported/correct. I suspect that I need to query the data differently or pre-sort them in code ahead of time? I'm not sure if this would be done in the View (what is Django's form of Controller?).. If anyone could point me in the right direction, that would be MUCH appreciated!

Answer

juliocesar picture juliocesar · Nov 28, 2013

There are several levels for display ordered models objects in template, each one overwrite the previous level:

  1. (MODEL LEVEL) Meta attribute ordering as shows @Bithin in his answer (more on django docs)
  2. (VIEW LEVEL) QuerySet order_by method as you have tried in your view example, which would works as you want if add other fields to sort:

    Customer.objects.order_by('state', 'city_name', 'customer_name')

    (more on django docs). Note that .all() is not needed here.

  3. (TEMPLATE LEVEL) regroup template tag need to use nested in your sample (more on django docs)