фильтр 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 ответов
я столкнулся с подобной ситуацией сегодня, и кажется, что из коробки 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."