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

Posted

技术标签:

【中文标题】django-rest-framework 按日期过滤=无【英文标题】:django-rest-framework filter by date=None 【发布时间】:2014-02-26 11:35:00 【问题描述】:

我正在使用django-rest-frameworkdjango-filter。我需要检索date 属性为None 的小部件列表,但无论我尝试什么查询,我都会得到空响应或完整的、未过滤的响应。

这是我定义视图集和过滤器集的方式。

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

【问题讨论】:

【参考方案1】:

更新: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

【讨论】:

【参考方案2】:

正在运行 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按“无日期”过滤

【讨论】:

【参考方案3】:

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

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”的第一个谷歌结果。

【讨论】:

【参考方案4】:

直接在过滤器的name 参数中将isnull 指定为'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 = []

【讨论】:

我无法让 *__isnull 使用上述代码风格。 问题似乎在于 django_filters.BooleanFilter 无法正确理解 True/False。使用 from django_filters.rest_framework import filters, filter 然后 filterset.FilterSet 和 filters.BooleanFilter 工作,因为它似乎将 BooleanWidget 作为参数传递给它。【参考方案5】:

我今天遇到了类似的情况,似乎开箱即用的 django rest framework* 支持此过滤器:

~/your_endpoint/?date__isnull=True

这与等效的 ORM 查询的外观相匹配。如果这很难看,您可以使用 docs 示例将该查询参数转换为其他参数,而无需覆盖 get_queryset

我使用的是 2.4.3,但我不认为这是一个新事物

【讨论】:

您能给我们您的 DRF 设置吗?和视图类?它对我不起作用:/ @GuillaumeEsquevin,查看docs.djangoproject.com/en/dev/ref/models/querysets/…【参考方案6】:

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

【讨论】:

是否有任何特殊原因说明这不是针对所述问题的可接受和/或优雅的解决方案?工作正常。 @PaulMaurer 这不会自动为过滤器添加文档。为这些文档编写代码可能比使用 FilterSet 更难。

以上是关于django-rest-framework 按日期过滤=无的主要内容,如果未能解决你的问题,请参考以下文章

django-rest-framework:如何序列化已经包含 JSON 的字段?

django-rest-framework 是不是提供管理站点来管理模型?

断言错误:Django-rest-Framework

记录对 django-rest-framework 的请求

django-rest-framework、多表模型继承、ModelSerializers 和嵌套序列化器

为啥 django-rest-framework 不显示 OneToOneField 数据 - django