【问题标题】:django-rest-framework filter by date=Nonedjango-rest-framework 按日期过滤=无
【发布时间】: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()

【问题讨论】:

    标签: django-rest-framework django-filter


    【解决方案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,但我不认为这是一个新事物

          【讨论】:

          【解决方案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 更难。
          猜你喜欢
          • 2020-03-09
          • 1970-01-01
          • 2016-09-08
          • 2021-06-25
          • 1970-01-01
          • 2018-04-23
          • 1970-01-01
          • 2019-03-01
          • 2020-04-27
          相关资源
          最近更新 更多