django-rest-framework按日期过滤=无

时间:2014-02-03 04:23:09

标签: django-rest-framework django-filter

我正在使用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()

6 个答案:

答案 0 :(得分:8)

直接在过滤器的isnull参数中指定name 'date__isnull'似乎对Django REST Framework 3.1.3起作用。

class WidgetFilter(django_filters.FilterSet):
    date = django_filters.DateTimeFilter(name='date')
    no_date = django_filters.BooleanFilter(name='date__isnull')
    class Meta:
        model = Widget
        fields = []

答案 1 :(得分:6)

我今天遇到了类似的情况,看起来好像开箱即用django rest framework *支持这个过滤器:

~/your_endpoint/?date__isnull=True

这与等效ORM查询的外观相匹配。如果这很丑陋,您可以使用文档示例将该查询参数转换为其他内容而不必覆盖get_queryset

  • 我使用2.4.3,但我不相信这是新事物

答案 2 :(得分:4)

如果没有更优雅的方式,这就是我提出的解决方法,但我仍然想知道使用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()

答案 3 :(得分:3)

正在运行django-filter==1.0.4djangorestframework==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

过滤“无日期”

答案 4 :(得分:0)

我已经为选择过滤器做了这个,这(可以说)更有用:

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)

我知道这并没有完全回答你的问题,但这是" django rest framework filter null的第一个google结果。"

答案 5 :(得分:0)

更新:name现在必须是field_name ...,而filter_class现在是filterset_class

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')

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