Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在Django中搜索多个模型中的字段_Python_Django_Django Models_Django Rest Framework - Fatal编程技术网

Python 在Django中搜索多个模型中的字段

Python 在Django中搜索多个模型中的字段,python,django,django-models,django-rest-framework,Python,Django,Django Models,Django Rest Framework,假设 名为教育的模型包含字段学位和字段,其他模型简历包含字段技能和角色 第三个模型是候选者,与上述模型有外键关系 我希望用户按其技能、角色、学位或字段搜索候选人 例如:如果传递了像{'java'、'developer'、'MS'、'IT'}这样的查询字符串,Django应该显示与查询字符串中任何一个值匹配的所有候选项。我认为Django中没有自动执行此操作的方法。但您可以使用Q始终或同时进行多个搜索。Q的基本用法如下: from django.db.models import Q Educati

假设

名为
教育
的模型包含字段
学位
字段
,其他模型
简历
包含字段
技能
角色

第三个模型是
候选者
,与上述模型有外键关系

我希望用户按其
技能
角色
学位
字段
搜索候选人


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

我认为Django中没有自动执行此操作的方法。但您可以使用Q始终或同时进行多个搜索。Q的基本用法如下:

from django.db.models import Q
Education.objects.filter(
    Q(degree__icontains=query) | Q(field__icontains=query)
要使用多个查询,您可以使用for语句轻松地将这些语句构建在一起(假设查询是查询字符串的列表或集合):

现在,您需要搜索多个模型,因此您还必须包括这些连接。从你的问题中不太清楚你想如何搜索,但我猜你基本上想搜索候选词,所有关键词都需要与找到的项目匹配。所以查询可以这样做:

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)
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',)

我不认为在django有一种自动的方式来做这件事。但您可以使用Q始终或同时进行多个搜索。Q的基本用法如下:

from django.db.models import Q
Education.objects.filter(
    Q(degree__icontains=query) | Q(field__icontains=query)
要使用多个查询,您可以使用for语句轻松地将这些语句构建在一起(假设查询是查询字符串的列表或集合):

现在,您需要搜索多个模型,因此您还必须包括这些连接。从你的问题中不太清楚你想如何搜索,但我猜你基本上想搜索候选词,所有关键词都需要与找到的项目匹配。所以查询可以这样做:

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)
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',)

如果您使用Django Rest框架(DRF)执行此操作,您将希望使用as

为了实现您在我的项目中所说的,我创建了一个django_过滤器的通用扩展。过滤器:

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_过滤器中使用。过滤器集
如下:

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)
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,)
将在至少一个字段
field\u foo
bar
baz
中返回包含所有
foo
de
fa
的所有
SampleSet

如果将参数
token\u reducer
指定为
运算符或
,则该查询将返回所有
样本集
,这些样本集至少在
字段
baz
中的一个字段中具有
foo
de
fa


最后,
token\u prefix
token\u suffix
是插入通配符(子字符串匹配)或其他前缀或后缀的一种方法。

如果使用Django Rest Framework(DRF)执行此操作,则需要使用as

为了实现您在我的项目中所说的,我创建了一个django_过滤器的通用扩展。过滤器:

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_过滤器中使用。过滤器集
如下:

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)
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,)
将在至少一个字段
field\u foo
bar
baz
中返回包含所有
foo
de
fa
的所有
SampleSet

如果将参数
token\u reducer
指定为
运算符或
,则该查询将返回所有
样本集
,这些样本集至少在
字段
baz
中的一个字段中具有
foo
de
fa

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

我使用它在Django Rest框架中搜索多个模型。确保仔细阅读文档,尤其是说明如何设置端点的文档。它的构建和文档记录似乎非常完善,支持我所期望的一切,如限制和过滤器。

我使用它在Django Rest框架中搜索多个模型。确保仔细阅读文档,尤其是说明如何设置端点的文档。它似乎构建得很好,文档化程度很高,支持我所期望的一切,比如限制和过滤器