Search code examples
djangopaginationdjango-pagination

How to write a paginator which would set a default page depending on the current date?


I have a huge list of lessons ordered by the date. I want to include paginator so it would always set default page on a current date(if such lessons exists, and if not the nearest future lessons).Is it even possible to do?

from django.contrib.auth.models import Lesson
from django.core.paginator import Paginator

lesson_list = Lesson.objects.all().order_by('datetime')
paginator = Paginator(user_list, 10)

Solution

  • You can annotate your QuerySet with a conditional expression based on whether or not the Lesson is today, and then use that annotation to sort your QuerySet.

    from datetime import date  # for typing
    from django.db.models import BooleanField, Case, Value, When
    from django.utils import timezone
    
    current_date: date = timezone.now().date()
    
    lesson_list = Lesson.objects.annotate(
        lesson_today=Case(
            When(datetime__date=current_date, then=Value(True)),
            default=Value(False),
            output_field=BooleanField()
        )
    ).order_by('-lesson_today', '-datetime')
    
    • Get the current datetime by using Django's built-in timezone utility. Use .date() to get a date object from the datetime object.
    • annotate() the QuerySet with a field named lesson_today.
    • The value of lesson_today is a boolean Case() where Lesson.datetime has a year, month and day that matches the current date. Use the __date subscript to ensure we're not trying to match on the hour, minute and second components of the DateTimeField.
    • Ordering by -lesson_today first means that objects where lesson_today=True are sorted first. The remaining objects are then sorted in reverse chronological order (e.g. future lessons).