Как указать пользовательский выбор для функции django_filters DateRangeFilter?

Я использую функцию django_filters DateRangeFilter(). Мой класс фильтра выглядит так:

class ListingFilter(django_filters.FilterSet):
    ship_docking = django_filters.DateRangeFilter()
    class Meta:
        model = Listing
        fields = ['orig', 'dest', 'ship_sailing', 'ship_docking']

Я хочу изменить выбор диапазона. По умолчанию выбраны значения «Сегодня», «Вчера», «Последние 7 дней» и т. д. Как указать другой список вариантов?

Спасибо и с уважением... Пол (новичок в Джанго)


person Paul Offord    schedule 23.07.2020    source источник


Ответы (1)


Проверяя исходный код для django-filter и DateRangeFilter, мы видим, что на __init__ он проверяет, были ли переданы наборы вариантов и наборы фильтров, и если они пусты, используются значения по умолчанию.

class DateRangeFilter(ChoiceFilter):
    choices = [
            ('today', _('Today')),
            ('yesterday', _('Yesterday')),
            ('week', _('Past 7 days')),
            ('month', _('This month')),
            ('year', _('This year')),
        ]
    
        filters = {
            'today': lambda qs, name: qs.filter(**{
                '%s__year' % name: now().year,
                '%s__month' % name: now().month,
                '%s__day' % name: now().day
            }),
            'yesterday': lambda qs, name: qs.filter(**{
                '%s__year' % name: (now() - timedelta(days=1)).year,
                '%s__month' % name: (now() - timedelta(days=1)).month,
                '%s__day' % name: (now() - timedelta(days=1)).day,
            }),
            'week': lambda qs, name: qs.filter(**{
                '%s__gte' % name: _truncate(now() - timedelta(days=7)),
                '%s__lt' % name: _truncate(now() + timedelta(days=1)),
            }),
            'month': lambda qs, name: qs.filter(**{
                '%s__year' % name: now().year,
                '%s__month' % name: now().month
            }),
            'year': lambda qs, name: qs.filter(**{
                '%s__year' % name: now().year,
            }),
        }
    
        def __init__(self, choices=None, filters=None, *args, **kwargs):
            if choices is not None:
                self.choices = choices
            if filters is not None:
                self.filters = filters

Все, что вам нужно сделать, это создать список наборов для вашего выбора, а затем скопировать формат для ваших пользовательских фильтров, а затем:

class ListingFilter(django_filters.FilterSet):
    // Put custom choices and filter variables here
    choices = [...]
    filters = { ... }
    ship_docking = django_filters.DateRangeFilter(choices=choices, filters=filters)
    class Meta:
        model = Listing
        fields = ['orig', 'dest', 'ship_sailing', 'ship_docking']
person Harben    schedule 23.07.2020
comment
Спасибо, Харбен, отлично работает. Мне пришлось скопировать функцию _truncate из исходников django_filters, но в остальном никаких проблем: def _truncate(dt): return dt.date() - person Paul Offord; 24.07.2020