假設,搜索字段在Django
名爲Education
模型包含字段degree
和field
,和其他模型Resume
包含字段skill
和role
。
第三種模式是Candidates
並與上述機型外鍵關係。
我希望用戶按skill
,role
,degree
或field
搜索候選人。
例如:如果傳遞類似{'java','developer','MS','IT'}
的查詢字符串,Django應顯示與查詢字符串中的任何一個值匹配的所有候選字符。
假設,搜索字段在Django
名爲Education
模型包含字段degree
和field
,和其他模型Resume
包含字段skill
和role
。
第三種模式是Candidates
並與上述機型外鍵關係。
我希望用戶按skill
,role
,degree
或field
搜索候選人。
例如:如果傳遞類似{'java','developer','MS','IT'}
的查詢字符串,Django應顯示與查詢字符串中的任何一個值匹配的所有候選字符。
如果你使用Django的REST框架(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
請求l邁克:
http://www.example.com/rest/SampleSet/?multi_field_srch=foo,de,fa,fa
會傳回的foo
,de
,和fa
所有在田裏field_foo
,bar
或baz
的至少一個所有SampleSet
的。
如果指定參數token_reducer
是operator.or_
,那麼查詢將返回所有SampleSet
S作的foo
,de
,或fa
任何在田裏field_foo
的至少一個,bar
或baz
。
最後,token_prefix
和token_suffix
是插入通配符(子字符串匹配)或其他前綴或後綴的一種方式。
我不認爲有一個自動的方式在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)