django-rest-framework 按日期过滤=无
Posted
技术标签:
【中文标题】django-rest-framework 按日期过滤=无【英文标题】:django-rest-framework filter by date=None 【发布时间】:2014-02-26 11:35:00 【问题描述】:我正在使用django-rest-framework
和django-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.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按“无日期”过滤
【讨论】:
【参考方案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
【讨论】:
您能给我们您的 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 是不是提供管理站点来管理模型?