如果您使用 Django Rest Framework (DRF) 执行此操作,您将希望使用 django_filters 作为 referenced by DRF。
为了在我的项目中执行您所说的操作,我创建了 django_filters.Filter 的通用扩展:
import operator
from django.db.models import Q
import django_filters
class MultiFieldFilter(django_filters.Filter):
def __init__(self,names,*args,**kwargs):
if len(args) == 0:
kwargs['name'] = names[0]
self.token_prefix = kwargs.pop('token_prefix','')
self.token_suffix = kwargs.pop('token_suffix','')
self.token_reducer = kwargs.pop('token_reducer',operator.and_)
self.names = names
django_filters.Filter.__init__(self,*args,**kwargs)
def filter(self,qs,value):
if value not in (None,''):
tokens = value.split(',')
return qs.filter(
reduce(
self.token_reducer,
[
reduce(
operator.or_,
[Q(**{
'%s__icontains'%name:
(self.token_prefix+token+self.token_suffix)})
for name in self.names])
for token in tokens]))
return qs
这在django_filter.FilterSet 中使用,如下所示:
class SampleSetFilter(django_filters.FilterSet):
multi_field_search = MultiFieldFilter(names=["field_foo", "bar", "baz"],lookup_type='in')
class Meta:
model = SampleSet
fields = ('multi_field_srch',)
实例化如下:
class SampleSetViewSet(viewsets.ModelViewSet):
queryset = SampleSet.objects.all()
serializer_class = SampleSetSerializer
filter_class = SampleSetFilterSet # <- and vvvvvvvvvvvvvvvvvvvvvvvvvvvv
filter_backends = (filters.OrderingFilter, filters.DjangoFilterBackend,)
最后,GET 请求如下:
http://www.example.com/rest/SampleSet/?multi_field_srch=foo,de,fa,fa
将返回所有SampleSet 在至少一个字段@987654334 中所有 foo、de、和 fa @、bar 或 baz。
如果您将参数token_reducer 指定为operator.or_,则该查询将返回所有具有foo、de、或任何的SampleSets /em> fa 至少在 field_foo、bar 或 baz 字段之一中。
最后,token_prefix 和 token_suffix 是一种插入通配符(子字符串匹配)或其他前缀或后缀的方法。