在Django中的多个模型中搜索字段 [英] Search fields in multiple models in Django

查看:152
本文介绍了在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):
multi_field_search = MultiFieldFilter(names = [field_foo,bar baz],lookup_type ='in')
class Meta:
model = SampleSet
fields =('multi_field_srch',)
pre>

实例化如下:

  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> fa baz



如果您将参数 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 fields degree and field, and other model Resume contains the fields skill and role.

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 or field.

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 of foo, de, and fa in at least one of the fields field_foo, bar, or baz.

If you specify parameter token_reducer to be operator.or_, then that query would return all SampleSets that have any of foo, de, or fa in at least one of the fields field_foo, bar, or baz.

Finally, token_prefix and token_suffix are a way to insert wild cards (substring matching) or other prefixes or suffixes.

这篇关于在Django中的多个模型中搜索字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆