фильтр django-rest-framework по дате=нет

я использую django-rest-framework С django-filter. Мне нужно получить список виджетов, где date недвижимость None, но независимо от того, какой запрос я пробовал, я получаю либо пустые ответы, либо полные, нефильтрованные ответы.

вот как я определил viewset и filterset.

class WidgetFilter(django_filters.FilterSet):
    date = django_filters.DateTimeFilter(name='date', lookup_type='exact')
    no_date = django_filters.DateTimefilter(name='date', lookup_type='isnull')
    class Meta:
        model = Widget
        fields = ['date',]

class WidgetSet(viewsets.ModelViewSet):
    model = Widget
    filter_class = WidgetFilter

следующие запросы приводят к пустой [] ответы:

?date=None
?date=0
?date=NULL
?date=False
?date=2012-05-24T11:20:06Z  # a known and correct date

следующие запросы приводят к тому, что все объекты вернулся:

?date=
?no_date=True
?no_date=False
?no_date=1
?no_date=0

любая помощь очень ценится! Я не смог найти никакой информации об использовании времени (или передает None как значение фильтра) с django-filter в частности, через django-rest-framework.


в случае, если нет более элегантного способа, вот как я обошел свой обходной путь, но я все равно хотел бы знать о решении, которое использует django-filter, если таковой существует.

class WidgetSet(viewsets.ModelViewSet):
    model = Widget

    def get_queryset(self):
        if 'no_date' in self.request.QUERY_PARAMS:
            return self.model.objects.filter(date=None)
        return self.model.objects.all()

5 ответов


задание isnull непосредственно в фильтре


я столкнулся с подобной ситуацией сегодня, и кажется, что из коробки Django Rest framework* поддерживает этот фильтр как:

~/your_endpoint/?date__isnull=True

Это соответствует тому, как будет выглядеть эквивалентный запрос ORM. Если это некрасиво, вы можете использовать пример docs для преобразования этого параметра запроса во что-то другое без переопределения get_queryset

  • Я использую 2.4.3, но я не верю, что это новая вещь

в случае, если нет более элегантного способа, вот как я обошел свой обходной путь, но я все равно хотел бы знать о решении, которое использует django-filter, если таковой существует.

class WidgetSet(viewsets.ModelViewSet):
    model = Widget

    def get_queryset(self):
        if 'no_date' in self.request.QUERY_PARAMS:
            return self.model.objects.filter(date=None)
        return self.model.objects.all()

под управлением django-filter==1.0.4 и djangorestframework==3.6.3.

правильный ответ не работал, потому что пути модуля изменились в django-filter (BooleanFilter перешел на django_filters.rest_framework).

и __isnull тоже не сработало, мне пришлось использовать lookup_expr:

from django_filters import rest_framework as filters


class WidgetFilter(filters.FilterSet):
    no_date = filters.BooleanFilter(name='date', lookup_expr='isnull')

    class Meta:

        model = Widget
        fields = ( 'date')

получил ответ от https://github.com/carltongibson/django-filter/issues/743

теперь я могу фильтровать по "дата" с помощью http://localhost:8000/widgets/?no_date=True


Я сделал это для выбора фильтров, что (возможно) более полезно:

class NullableChoiceFilter(django_filters.ChoiceFilter):
    def __init__(self, **kwargs):
        choices = dict(kwargs['choices'])
        null_text = choices.pop(None, 'null')
        kwargs['choices'] = ((None, '------'), ('null', null_text)) + tuple(choices.items())
        super().__init__(**kwargs)

    def filter(self, qs, value):
        if value == 'null':
            return super().filter(qs, Lookup(lookup_type='isnull', value=True))
        else:
            return super().filter(qs, value)

а то

class MyFilterSet(filters.FilterSet):
    class Meta:
        model = ...

    @classmethod
    def filter_for_lookup(cls, f, lookup_type):
        if lookup_type == 'exact' and f.choices:
            return NullableChoiceFilter, {'choices': f.choices}
        return filters.FilterSet.filter_for_lookup(f, lookup_type)

Я знаю, что это не отвечает точно на ваш вопрос, но это первый результат google для "django Rest framework filter null."