Darkstarone
Darkstarone

Reputation: 4730

Django ORM extract weekday as string from queryset

What I'm trying to do is annotate a queryset with the weekday strings ("monday", "tuesday" etc).

I understand how to get the int values:

queryset = queryset.annotate(
  weekday_int=ExtractWeekDay("date"),
)

But I'm having trouble getting the string values themselves. I've tried using an ExpressionWrapper, but F objects don't seem to play well with Date objects.

I'm using postgres as my underlying database but can't find a related lookup_name for the generic Extract.

Upvotes: 3

Views: 529

Answers (2)

Nathan
Nathan

Reputation: 509

When I tried the accepted answer on Django 4.2, there's a warning about ExtractWeekDay has no convert_value method.
A solution using Case + When that parse weekday_int onto week day name:

from django.db.models import Case, Value, When
from django.db.models.functions import ExtractIsoWeekDay


queryset = queryset.annotate(
    # ISO-8601 week day with day 1 being Monday and day 7 being Sunday.
    weekday_int=ExtractIsoWeekDay("date"), weekday_string=Case(
        When(weekday_int=1, then=Value('Monday')),
        When(weekday_int=2, then=Value('Tuesday')),
        When(weekday_int=3, then=Value('Wednesday')),
        When(weekday_int=4, then=Value('Thursday')),
        When(weekday_int=5, then=Value('Friday')),
        When(weekday_int=6, then=Value('Saturday')),
        When(weekday_int=7, then=Value('Sunday')),
        default=Value("")
    )
)

Upvotes: 0

Andrey Nelubin
Andrey Nelubin

Reputation: 3294

I've tested this:

import calendar


class ExtractWeekDayName(ExtractWeekDay):
    @property
    def output_field(self):
        return CharField()

    def convert_value(self, value, expression, connection, context):
        v = super(ExtractWeekDayName, self).convert_value(value, expression, connection)
        try:
            return calendar.day_name[int(v)].lower()
        except (ValueError, IndexError):
            return 'error'
        except TypeError: # NoneType
            return ''

Seems legit.

Upvotes: 2

Related Questions