在Django中的多个模型中搜索字段 [英] Search fields in multiple models in Django
问题描述
假设
名为教育
的模型包含字段 degree
和字段
和其他模型简历
包含字段技能
和角色
。
第三个模型是候选人
并且与上述模型有外键关系。
我希望用户通过他们的技能搜索候选人
,角色
,学位
或字段
p>
例如:如果查询字符串像 {'java','开发者','MS','IT'}
传递,Django应显示与查询字符串中任何一个值相匹配的所有候选者。
请使用Django Rest Framework(DRF)来进行此操作,您将需要使用 django_filters 作为由DRF引用。
为了做我在项目中谈论的内容,我创建了一个通用扩展一个 django_filters.Filter
:
import operator
从django.db.models导入Q
import django_filters
class MultiFieldFilter(django_filters.Filter):
def __init __(self,names,* args,** kwargs):
如果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。过滤器.__ init __(self,* args,** kwargs)
def filter(self,qs,value):
如果值不在(无,'):
tokens = value.split(',')
return qs.filter(
reduce(
self.token_reducer,
[
reduce(
operator.or_,
[Q(** {
'%s__icontains'%name:
(self.token_prefix + token + self.token_suffix)})
在self.names中的名称])
用于令牌中的令牌]))
return qs
这在 django_filter.FilterSet
中使用,如下所示: / p>
class SampleSetFilter(django_filters.FilterSet):
pre>
multi_field_search = MultiFieldFilter(names = [field_foo,bar baz],lookup_type ='in')
class Meta:
model = SampleSet
fields =('multi_field_srch',)
实例化如下:
class SampleSetViewSet(viewset s.ModelViewSet):
queryset = SampleSet.objects.all()
serializer_class = SampleSetSerializer
filter_class = SampleSetFilterSet#< - 和vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
filter_backends =(filters.OrderingFilter,filters .DjangoFilterBackend,)
最后,一个
GET
请求像:http://www.example.com/rest/SampleSet/?multi_field_srch=foo,de,fa, fa
将返回所有
SampleSet
拥有foo
,de
,和 <$至少有一个字段field_foo
,bar
中的c $ c> fabaz
。
如果您将参数
token_reducer
指定为operator.or _
,那么该查询将返回所有SampleSet
s,其中任何 code> foo ,de
,或fa
至少在一个字段field_fo中o
,bar
或baz
。
最后,
token_prefix
和token_suffix
是一种插入通配符(子串匹配)或其他前缀的方法或后缀。Suppose,
A model named
Education
contains the fieldsdegree
andfield
, and other modelResume
contains the fieldsskill
androle
.A third model is
Candidates
and has a foreign key relation with the above models.I want the user to search candidates by their
skill
,role
,degree
orfield
.For example: if a query string like
{'java','developer','MS','IT'}
is passed, Django should show the all the candidates matching any one of the values in the query string.解决方案If you're doing this with the Django Rest Framework (DRF), you will want to use django_filters as referenced by DRF.
To do what you're talking about in my project, I created a generic extension of a
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
This is used in a
django_filter.FilterSet
like this: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',)
Which is instantiated like:
class SampleSetViewSet(viewsets.ModelViewSet): queryset = SampleSet.objects.all() serializer_class = SampleSetSerializer filter_class = SampleSetFilterSet # <- and vvvvvvvvvvvvvvvvvvvvvvvvvvvv filter_backends = (filters.OrderingFilter, filters.DjangoFilterBackend,)
Finally, a
GET
request like:http://www.example.com/rest/SampleSet/?multi_field_srch=foo,de,fa,fa
will return all
SampleSet
's that have all offoo
,de
, andfa
in at least one of the fieldsfield_foo
,bar
, orbaz
.If you specify parameter
token_reducer
to beoperator.or_
, then that query would return allSampleSet
s that have any offoo
,de
, orfa
in at least one of the fieldsfield_foo
,bar
, orbaz
.Finally,
token_prefix
andtoken_suffix
are a way to insert wild cards (substring matching) or other prefixes or suffixes.这篇关于在Django中的多个模型中搜索字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!