Explain Codes LogoExplain Codes Logo

Django order_by query set, ascending and descending

python
django
queryset
ordering
Anton ShumikhinbyAnton Shumikhin·Oct 26, 2024
TLDR

Sort a Django QuerySet with .order_by(): 'field' for ascending, '-field' for descending.

Example:

# Once upon a time, we ordered in ascending road ascending_qs = MyModel.objects.order_by('field') # Then decided to walk down the descending Road descending_qs = MyModel.objects.order_by('-field')

Logical primer to ordering

Understanding the guts of Django order_by makes using it a breeze.

Looking to order by a related model field? Here's how:

# Sorting party by related friends' age queryset = MyModel.objects.order_by('relatedmodel__field')

Smushing multiple fields in order_by

Want to sort on several things? Chain them:

# Sorting concert by date (rock before pop), then by band name. Party on! queryset = MyModel.objects.order_by('-date', 'name')

Setting a default ordering

Picky about your default list order? Set it up in the Meta class:

class MyModel(models.Model): # ... fields here ... class Meta: # It's like mama always said, 'Name first, age second.' ordering = ('name', '-age')

Dynamic ordering

Life changes and so can your order_by:

# Life's pretty vanilla... order_field = 'field' # or '-field' for descending # ...until it's not queryset = MyModel.objects.order_by(order_field)

Digging deeper into order_by

Play with order_by. Understand it, bend it to your will. Here's how:

How ordering treats null values

Deal with those pesky null pointers:

# When life gives you nulls, sort them to the last queryset = MyModel.objects.order_by('field', 'other_field') # Unless you want 'em first. We don't judge. queryset = MyModel.objects.order_by(F('field').asc(nulls_first=True))

Mind your performance

Remember, order_by can also mean wait_for_it on large datasets:

# Ordering for ants? Fast. # Ordering for elephants? Umm... large_query_set = LargeModel.objects.order_by('-date', 'category', 'name')

It's your order, flip it!

Don't let order_by control you. Exercise your right to reverse:

# Ordered pizza but felt like sushi? Just reverse! queryset = MyModel.objects.order_by('field').reverse()

Advanced ordering methods

Master order_by, use it like you invented it. Here are cool tricks:

Null-safe fields with SQL expressions

Turn null feel-sorry-for-me into null look-at-me-nailing-it:

# When life gives you nulls, make zero lemonades! queryset = MyModel.objects.annotate(null_safe_field=Coalesce('field_with_nulls', 0)).order_by('null_safe_field')

Optimising JOINs in ordering

Too many JOIN operations? Don't get stuck, get optimizing:

# Optimise queryset ordering with foreign key fields. MyModel.objects.select_related('foreign_key_field').order_by('foreign_key_field__related_field')

Custom ordering functions

Conquer world, or just simply custom sort it:

# Be that nerdy party-goer who orders people by name length. from django.db.models import Func class Length(Func): function = 'LENGTH' queryset = MyModel.objects.annotate(field_length=Length('name')).order_by('field_length')

Error-proofing

Remember, the only certainties in life are death and AttributeError:

# Well, we tried, and we caught. Life moves on. try: queryset = MyModel.objects.order_by('nonexistent_field') except FieldError: queryset = MyModel.objects.order_by('default_field')