2015-06-23 191 views
1

假设,搜索字段在Django

名为Education模型包含字段degreefield,和其他模型Resume包含字段skillrole

第三种模式是Candidates并与上述机型外键关系。

我希望用户按skill,role,degreefield搜索候选人。

例如:如果传递类似{'java','developer','MS','IT'}的查询字符串,Django应显示与查询字符串中的任何一个值匹配的所有候选字符。

回答

0

如果你使用Django的REST框架(DRF)这样做,你将要使用django_filtersreferenced 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请求l迈克:

http://www.example.com/rest/SampleSet/?multi_field_srch=foo,de,fa,fa 

会传回的foodefa所有在田里field_foobarbaz的至少一个所有SampleSet的。

如果指定参数token_reduceroperator.or_,那么查询将返回所有SampleSet S作foodefa任何在田里field_foo的至少一个,barbaz

最后,token_prefixtoken_suffix是插入通配符(子字符串匹配)或其他前缀或后缀的一种方式。

0

我不认为有一个自动的方式在Django做到这一点。但是你可以总是或多个搜索一起使用Q. Q的基本用法如下:

from django.db.models import Q 
Education.objects.filter(
    Q(degree__icontains=query) | Q(field__icontains=query) 

要使用的语句(假设查询是一个列表或者设置使用多个查询,你可以很容易地建立起来,这些语句的查询字符串):

q = Q() 
for query in queries 
    q = q | Q(degree__icontains=query) | Q(field__icontains=query) 
Education.objects.filter(q) 

现在,您需要搜索多个模型,因此您还必须包含这些连接。这不是从你的问题十分清楚,你会如何想搜索,但我猜你想从根本上寻找候选人,所有的关键字必须被找到的项目相匹配。因此查询可以做这样的:

q = Q() 
for query in queries 
    q = (q & (Q(education__degree__icontains=query) | 
       Q(education__field__icontains=query) | 
       Q(resume__skill__icontains=query) | 
       Q(resume__role__icontains=query) 
       Q(skill__icontains=query) | 
       Q(role__icontains=query) | 
       Q(degree__icontains=query) | 
       Q(field__icontains=query))) 
return Candidate.objects.filter(q)