Raunak Agarwal
Raunak Agarwal

Reputation: 7228

Django Ordering Query Set in ascending order

I want to order my QuerySet in ascending order for this case:

PRIORITY_CHOICES = (
(1, "P1"),
(2, "P2"),
(3, "P3"),
(4, "P4"),
(5, "P5"),
)

class Task(models.Model):
     name = models.CharField(max_length=255)
     priority = models.PositiveIntegerField(choices=PRIORITY_CHOICES)

Now, since, the priority can accept None values. The problem is with ordering the Query set when I do this in my View code:

task_list = Task.objects.all().order_by("priority")

This returns me the query set with the objects arranged in ascending order of priority, with the None values first. I want the ascending list but I want to include the None values at the end. I have a huge database so, I am interested in accomplishing this at the database level.

Upvotes: 2

Views: 3764

Answers (3)

miyou995
miyou995

Reputation: 87

you can do it simply like this in the Model like this

class ModelName(models.Model):
    feild_1 = models.CharField( max_length=150)
    feild_2 = models.CharField( max_length=150, blank=True, null=True)

    class Meta:
        ordering = [F('order').asc(nulls_last=True)]

Upvotes: 0

Victor Gavro
Victor Gavro

Reputation: 1407

You can change order to descending using queryset.order_by('-field') (prepending "-" symbol), but there is no way in Django to tell how nulls should be sorted - it's database specific behavior. If using descending ordering still gives you null values first in your database - use queryset.extra(select={'order': 'custom_sql_function(priority)'}).order_by('order'), where custom_sql_function converts field to integer if it is null, and is specific for your database engine. For faster performance you can create db index on function(field).

Upvotes: 1

pyrospade
pyrospade

Reputation: 8078

This is probably your best option.

import itertools
q = itertools.chain(
        Task.objects.filter(priority__isnull=False).order_by("priority"),
        Task.objects.filter(priority__isnull=True))
# Then you can iterate over your custom order
result = [(x.name, x.priority) for x in q]

Upvotes: 4

Related Questions