Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ordering a Django QuerySet by a datetime's month/day?

I have a list of people, each person having a birthdate, which is predictably stored in a DateField. I'm trying to create a list of those people—sorted by the month and day of their birth (disregarding the year)—to have a sort of "who's birthday is coming up" display.

I can't seem to order a QuerySet by the person's datetime.month value. Is there any way that this could be done without having to resort to coercing to a list()?

Thanks in advance and please let me know if the question needs clarification.

like image 605
Bryan Veloso Avatar asked Nov 21 '10 03:11

Bryan Veloso


1 Answers

For django >= 2.1

You can sort the QuerySet by using month and day lookup names on DateField.

SomeModel.objects.order_by('birth_date__month', 'birth_date__day')

For django >= 1.10

Use database-function Extract to generate extra month and day columns by annotate method, then order_by these columns you can sort the QuerySet by their birthday only.

from django.db.models.functions import Extract

SomeModel.objects.annotate(
    birth_date__month = Extract('birth_date', 'month'),
    birth_date__day = Extract('birth_date', 'day')
).order_by('birth_date__month', 'birth_date__day')

For older django versions

For older django versions you can do the same using QuerySet.extra(), but you have to write database specific query.

  • MySQL

    SomeModel.objects.extra(select={
            'birth_date_month': 'MONTH(birth_date)',
            'birth_date_day': 'DAY(birth_date)'
        },
        order_by=['birth_date_month','birth_date_day']
    )
    
  • PostgreSQL

    SomeModel.objects.extra(select={
            'birth_date_month': 'EXTRACT(MONTH FROM birth_date)',
            'birth_date_day': 'EXTRACT(DAY FROM birth_date)'
        },
        order_by=['birth_date_month','birth_date_day']
    )
    
  • SQlite

    SomeModel.objects.extra(select={
            'birth_date_month': 'strftime("%m", birth_date)',
            'birth_date_day': 'strftime("%d", birth_date)'
        },
        order_by=['birth_date_month','birth_date_day']
    )
    
like image 51
Munim Munna Avatar answered Nov 05 '22 23:11

Munim Munna