Django фильтр по диапазону дат, но без учета года
Я знаю, что если я хочу отфильтровать результаты по диапазону дат, я просто использую что-то вроде
Sample.objects.filter(birthday__range=(start_date, end_date))
Но как мне отфильтровать по диапазону дат, исключающему год?
 Вы можете использовать функцию Extract на базе данных.
Например, этот простой запрос ниже возвращает элементы, у которых день рождения в 8-м месяце. Вы также можете извлечь день, месяц или год по своему усмотрению и отфильтровать по ним.
from django.db.models.functions import Extract
Sample.objects.annotate(birthday_month=Extract('birthday', 'month')).filter(birthday_month=8)
Дополнительная информация в документации.
https://docs.djangoproject.com/en/3.2/ref/models/database-functions/#extract
Вы можете использовать как фильтр, так и исключение. Фильтруйте, как вы сделали, а затем исключите год, например 2021
Sample.objects.filter(birthday__range=(start_date, end_date)).exclude(birthday_date__year=2021)
                    Мы можем работать с диапазоном дат с:
from datetime import timedelta
from django.db.models import Q
def filter_query(start_date, end_date):
    a = am, ad = start_date.month, start_date.day
    b = bm, bd = end_date.month, end_date.day
    end_date2 = end_date + timedelta(days=1)
    c = end_date2.month, end_date2.day
    if c == (2, 29) and a == (3, 1):
        return ~Q(birthday__month=2, birthday__day__gt=28)
    if a == c:
        return Q()
    if a <= b:
        if am == bm:
            return Q(birthday__month=am, birthday__day__range=(ad, bd))
        else:
            return (Q(birthday__month=am, birthday__day__gte=ad) |
                    Q(month__range=(am+1, bm-1)) |
                    Q(birthday__month=bm, birthday__day__lte=bd))
    else:
        return ~filter_query(end_date+timedelta(days=1), start_date-timedelta(days=1))
 Это вернет объект Q, который затем можно использовать для фильтрации набора запросов, например:
Sample.objects.filter(filter_query(date(2020, 12, 15), date(2021, 1, 16)))
В основном существует пять случаев:
-  если 
end_date- 28 февраля, а дата начала - 1 марта, то мы исключаем 29 февраля. .
 -  если 
end_dateплюс один день совпадает с датой начала, то нам не нужно фильтровать; -  если 
start_dateменьше чемend_dateи месяцы совпадают, то фильтруем по этому месяцу, а по дням проверяем диапазон; -  если 
start_dateменьше чемend_dateи месяцы не совпадают, тогда мы ищем диапазоны:-  элементы с одинаковым месяцем 
start_dateи с днем, большим, чем месяцstart_date; -  элементы с месяцем между следующим месяцем 
start_dateи меньшим, чем предыдущий месяцend_date; и -  элементы с тем же месяцем, что и 
end_dateи днем меньше или равным днюend_date. 
 -  элементы с одинаковым месяцем 
 -  если конечная дата меньше начальной, то мы возвращаем отрицание 
end_dateплюс один день иstart_dateминус один день.