erg*_*sto 2 python django django-filter django-filters django-rest-framework
这是我正在使用的filterset的一个略微简化的例子,我正在使用DjangoFilterBackend for Django Rest Framework.我希望能够发送请求/api/bookmarks/?title__contains=word1&title__contains=word2并返回包含两个单词的结果,但是当前它忽略了第一个参数并且只忽略了word2的过滤器.
任何帮助将非常感谢!
class BookmarkFilter(django_filters.FilterSet):
class Meta:
model = Bookmark
fields = {
'title': ['startswith', 'endswith', 'contains', 'exact', 'istartswith', 'iendswith', 'icontains', 'iexact'],
}
class BookmarkViewSet(viewsets.ModelViewSet):
serializer_class = BookmarkSerializer
permission_classes = (IsAuthenticated,)
filter_backends = (DjangoFilterBackend,)
filter_class = BookmarkFilter
ordering_fields = ('title', 'date', 'modified')
ordering = '-modified'
page_size = 10
Run Code Online (Sandbox Code Playgroud)
主要问题是您需要一个了解如何操作多个值的过滤器.基本上有两种选择:
MultipleChoiceFilter(不推荐用于此实例)运用 MultipleChoiceFilter
class BookmarkFilter(django_filters.FilterSet):
title__contains = django_filters.MultipleChoiceFilter(
name='title',
lookup_expr='contains',
conjoined=True, # uses AND instead of OR
choices=[???],
)
class Meta:
...
Run Code Online (Sandbox Code Playgroud)
虽然这保留了您想要的语法,但问题是您必须构建一个选择列表.我不确定你是否可以简化/减少可能的选择,但是从袖口看起来你需要从数据库中获取所有标题,将标题拆分成不同的单词,然后创建一个集来删除重复项.根据您拥有的记录数量,这似乎很昂贵/慢.
习惯 Filter
或者,您可以创建自定义过滤器类 - 如下所示:
class MultiValueCharFilter(filters.BaseCSVFilter, filters.CharFilter):
def filter(self, qs, value):
# value is either a list or an 'empty' value
values = value or []
for value in values:
qs = super(MultiValueCharFilter, self).filter(qs, value)
return qs
class BookmarkFilter(django_filters.FilterSet):
title__contains = MultiValueCharFilter(name='title', lookup_expr='contains')
class Meta:
...
Run Code Online (Sandbox Code Playgroud)
用法(注意值以逗号分隔):
GET /api/bookmarks/?title__contains=word1,word2
Run Code Online (Sandbox Code Playgroud)
结果:
qs.filter(title__contains='word1').filter(title__contains='word2')
Run Code Online (Sandbox Code Playgroud)
语法稍有改变,但基于CSV的过滤器不需要构造一组不必要的选择.
请注意,?title__contains=word1&title__contains=word2由于窗口小部件无法呈现合适的html输入,因此无法支持语法.您可能需要使用SelectMultiple(这需要再次选择),或者在客户端上使用javascript来添加/删除具有相同name属性的其他文本输入.
不过多详细介绍,过滤器和过滤器只是Django表单的扩展.
Filter有一个形式Field,而这个形式又有一个Widget.FilterSet由Filters 组成.FilterSet根据其过滤器字段生成内部表单.每个过滤器组件的责任:
data QueryDict.filter()使用经过验证的值构造对查询集的调用.要为同一过滤器应用多个值,您需要一个过滤器,字段和小部件,以了解如何对多个值进行操作.
自定义过滤器通过混合实现这BaseCSVFilter一点,然后将"逗号分隔=>列表"功能混合到组合字段和窗口小部件类中.
我建议查看CSV mixins的源代码,但简而言之:
CharField或IntegerField)上的各个值来验证整个值列表.该字段还派生混合窗口小部件.该CSV滤波器的目的是与使用in和range查找,其接受的值的列表.在这种情况下,contains需要一个值.该filter()方法通过迭代值并将各个过滤器调用链接在一起来解决此问题.
| 归档时间: |
|
| 查看次数: |
3649 次 |
| 最近记录: |