示例#1
0
 def unionFilterQuerySet(self, queryset):
     queries = []
     base = queryset
     for field in self.union_fields:
         isNull = False
         value = self.request.GET.get(field, '')
         if value in ([], (), {}, '', None):
             continue
         value = value.split(',')
         newvalue = []
         for i in range(0, len(value)):
             if value[i] in (u'true', 'true'):
                 newvalue.append(True)
             elif value[i] in (u'false', 'false'):
                 newvalue.append(False)
             elif value[i] in (u'none', 'none'):
                 isNull = True
             else:
                 newvalue.append(value[i])
         queries.append(
             models.Q(**{LOOKUP_SEP.join([field, 'in']): newvalue}))
         if isNull:
             queries.append(
                 models.Q(**{LOOKUP_SEP.join([field, 'isnull']): isNull}))
     if len(queries) > 0:
         queryset = queryset.filter(reduce(operator.or_, queries))
         queryset = distinct(queryset, base)
     return queryset
示例#2
0
    def filter_queryset(self, request, queryset, view):
        self.request = request
        search_fields = getattr(view, 'search_fields', None)
        search_terms = self.get_search_terms(request)

        if not search_fields or not search_terms:
            return queryset

        orm_lookups = [
            self.construct_search(six.text_type(search_field))
            for search_field in search_fields
        ]

        base = queryset
        conditions = []
        sub_search = getattr(view, 'sub_search', None)
        if sub_search:
            sub_search = sub_search()
        for search_term in search_terms:
            queries = [
                models.Q(**{orm_lookup: search_term})
                for orm_lookup in orm_lookups
            ]
            if sub_search:
                queries += sub_search
            conditions.append(reduce(operator.or_, queries))
        queryset = queryset.filter(reduce(operator.and_, conditions))

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)
        return queryset
示例#3
0
    def filter_queryset(self, request, queryset, view):
        """Return queryset annotate s as Similarity

        similarity=TrigramSimilarity('name_cut', name_cut),
        s = 0.25 / similarity if name__startswith name
        s = 0.5 / similarity if name__contains name
        s = 1.0 / similarity if name_cut similar name_cut
        """
        name = self.get_search_terms(request)
        name_cut = get_name_cut(name)

        if not name or not name_cut:
            return queryset.annotate(s=Value(0.0, FloatField()))

        base = queryset
        queryset = queryset.annotate(similarity=TrigramSimilarity(
            'name_cut', name_cut), ).annotate(s=Case(
                When(name__startswith=name,
                     then=0.25 / (F('similarity') + 0.01)),
                When(name__contains=name, then=0.5 / (F('similarity') + 0.01)),
                default=1.0 / (F('similarity') + 0.01),
                output_field=FloatField(),
            )).filter(s__lt=9).order_by('s')

        return distinct(queryset, base)
示例#4
0
    def filter_queryset(self, request, queryset, view):
        search_terms = self.get_search_terms(request)
        if any([include_non_asc(x) for x in search_terms]):
            search_fields = getattr(view, 'search_fields', None)
        else:
            search_fields = getattr(view, 'pinyin_search_fields', None)

        if getattr(view, 'search_id_for_number', False):
            if len(search_terms) == 1 and search_terms[0].isdigit(
            ) and not search_terms[0].startswith('0'):
                return queryset.filter(pk=search_terms[0])

        if not search_fields or not search_terms:
            return queryset

        orm_lookups = [
            self.construct_search(six.text_type(search_field))
            for search_field in search_fields
        ]

        base = queryset
        conditions = []
        for search_term in search_terms:
            queries = [
                models.Q(**{orm_lookup: search_term})
                for orm_lookup in orm_lookups
            ]
            conditions.append(reduce(operator.or_, queries))
        queryset = queryset.filter(reduce(operator.and_, conditions))

        if self.must_call_distinct(queryset, search_fields):
            queryset = distinct(queryset, base)
        return queryset
示例#5
0
    def filter_queryset(self, request, queryset, view):
        search_terms = self.get_search_terms(request)
        if not search_terms:
            return queryset

        reference_descriptor = view.get_reference_descriptor()
        search_fields = reference_descriptor.get_search_fields()

        if not search_fields:
            raise exceptions.ValidationError(
                'ReferenceDescriptor for `{}` are not configured: incorrect `search_fields` field'
                .format(view.get_reference_model_name()))

        orm_lookups = [
            self.construct_search(six.text_type(search_field))
            for search_field in search_fields
        ]

        base = queryset
        for search_term in search_terms:
            queries = [
                models.Q(**{orm_lookup: search_term})
                for orm_lookup in orm_lookups
            ]
            queryset = queryset.filter(reduce(operator.or_, queries))

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)
        return queryset
示例#6
0
    def filter_queryset(self, request, queryset, view):
        search_fields = self.get_valid_fields(request, queryset, view)
        search_terms = self.get_search_terms(request)
        LOGGER.debug("[SearchFilter] search_terms=%s, search_fields=%s",
                     search_terms, search_fields)

        if not search_fields or not search_terms:
            return queryset

        orm_lookups = [
            self.construct_search(six.text_type(search_field))
            for search_field in search_fields
        ]

        base = queryset
        conditions = []
        for search_term in search_terms:
            queries = [
                models.Q(**{orm_lookup: search_term})
                for orm_lookup in orm_lookups
            ]
            conditions.append(reduce(operator.or_, queries))
        queryset = queryset.filter(reduce(operator.and_, conditions))

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)
        return queryset
示例#7
0
    def filter_queryset(self, request, queryset, view):
        search_fields = getattr(view, 'search_fields', None)

        search_terms = self.get_search_terms(request)

        if not search_fields or not search_terms:
            return queryset

        orm_lookups = [
            self.construct_search(six.text_type(search_field))
            for search_field in search_fields
        ]

        base = queryset
        for search_term in search_terms:
            queries = [
                models.Q(**{orm_lookup: search_term})
                for orm_lookup in orm_lookups
            ]
            queryset = queryset.filter(reduce(operator.or_, queries))

        # Filtering against a many-to-many field requires us to
        # call queryset.distinct() in order to avoid duplicate items
        # in the resulting queryset.
        return distinct(queryset, base)
示例#8
0
    def filter_queryset(self, request, queryset, view):
        """Return queryset annotate s as Similarity

        similarity=TrigramSimilarity('name_cut', name_cut),
        s = 0.25 / similarity if name__startswith name
        s = 0.5 / similarity if name__contains name
        s = 1.0 / similarity if name_cut similar name_cut
        """
        name = self.get_search_terms(request)
        name_cut = get_name_cut(name)

        if not name or not name_cut:
            return queryset.annotate(s=Value(0.0, FloatField()))

        base = queryset
        queryset = queryset.annotate(
            similarity=TrigramSimilarity('name_cut', name_cut),
        ).annotate(
            s=Case(
                When(name__startswith=name, then=0.25 / (F('similarity') + 0.01)),
                When(name__contains=name, then=0.5 / (F('similarity') + 0.01)),
                default=1.0 / (F('similarity') + 0.01),
                output_field=FloatField(),
            )
        ).filter(s__lt=9).order_by('s')

        return distinct(queryset, base)
示例#9
0
    def filter_queryset(self, request, queryset, view):
        search_fields = getattr(view, 'search_fields', None)
        search_terms = self.get_search_terms(request)

        if not search_fields or not search_terms:
            return queryset

        orm_lookups = [
            self.construct_search(six.text_type(search_field))
            for search_field in search_fields
        ]

        base = queryset
        for search_term in search_terms:
            queries = [
                models.Q(**{orm_lookup: search_term})
                for orm_lookup in orm_lookups
            ]
            queryset = queryset.filter(reduce(operator.or_, queries))

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this is possible, for performance reasons.
            queryset = distinct(queryset, base)
        return queryset
示例#10
0
    def filter_queryset(self, request, queryset, view):
        search_fields = self.get_search_fields(view, request)
        search_terms = self.get_search_terms(request)

        if not search_fields or not search_terms:
            return queryset

        orm_lookups = [
            self.construct_search(str(search_field))
            for search_field in search_fields
        ]

        base = queryset
        if self.required_m2m_optimization(view):
            queryset = self.optimized_queryset_filter(queryset, search_terms,
                                                      orm_lookups)
        else:
            queryset = self.chained_queryset_filter(queryset, search_terms,
                                                    orm_lookups)

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)
        return queryset
示例#11
0
    def filter_queryset(self, request, queryset, view):
        search_terms = self.get_search_terms(request)
        search_text_fields = getattr(view, 'search_text_fields', [])
        search_int_fields = getattr(view, 'search_int_fields', [])
        search_field_lookup = getattr(view, 'search_field_lookup', None)
        search_api_url = getattr(view, 'search_api_url', None)

        if not search_terms:
            return queryset

        base = queryset

        # First check all integer fields and return if matches
        int_queries = []
        for int_field in search_int_fields:
            values = filter(lambda x: x.isnumeric(), search_terms)
            if values:
                int_queries += [
                    models.Q(**{'{}__in'.format(int_field): values})
                ]

        if int_queries:
            int_queryset = queryset.filter(reduce(operator.or_, int_queries))
            if int_queryset:
                return int_queryset

        # If integer fields return nothing, use text lookup
        text_lookups = [
            self.construct_text_search(six.text_type(search_field))
            for search_field in search_text_fields
        ]

        for search_term in search_terms:
            queries = []
            if search_text_fields:
                cleaned_search_term = NON_ALPHANUMERIC.sub('', search_term)
                queries += [
                    models.Q(**{text_lookup: cleaned_search_term})
                    for text_lookup in text_lookups
                ]

            if search_field_lookup and search_api_url:
                lookup_ids = self.get_lookup_ids_from_search_term(request, search_api_url, search_term)
                if lookup_ids:
                    queries += [
                        models.Q(**{'{}__in'.format(search_field_lookup): lookup_ids})
                    ]

            if queries:
                queryset = queryset.filter(reduce(operator.or_, queries))

        # Filtering against a many-to-many field requires us to
        # call queryset.distinct() in order to avoid duplicate items
        # in the resulting queryset.
        return distinct(queryset, base)
示例#12
0
    def filter_queryset(self, request, queryset, view):
        search_fields = getattr(view, 'search_fields', None)
        search_terms = self.get_search_terms(request)

        base = queryset
        queryset = self.apply_filters(queryset, search_fields, search_terms)
        queryset = self.apply_search(queryset, search_fields, search_terms)

        if search_fields and self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)

        return queryset
示例#13
0
    def filter_queryset(self, request, queryset, view):
        """
        Case-insensitive search filtering
        """
        search_fields = self.get_search_fields(view, request)
        search_terms = self.get_search_terms(request)

        if not search_fields or not search_terms:
            return queryset

        orm_lookups = []
        orm_search_fields = []
        queryset_by_func_ids = []
        for search_field in search_fields:
            orm_lookup = self._construct_search(str(search_field))
            if orm_lookup is not None:
                orm_search_fields.append(search_field)
                orm_lookups.append(orm_lookup)
            else:
                self._filter_by_external_func(queryset_by_func_ids,
                                              search_field[1:], queryset,
                                              search_terms)

        base = queryset
        conditions = []
        for search_term in search_terms:
            queries = [
                models.Q(**{orm_lookup: search_term})
                for orm_lookup in orm_lookups
            ]
            conditions.append(reduce(operator.or_, queries))
        queryset = queryset.filter(reduce(operator.and_, conditions))

        if queryset_by_func_ids:
            queryset |= base.filter(id__in=queryset_by_func_ids)

        if self.must_call_distinct(queryset, orm_search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)

        return queryset
示例#14
0
    def filter_queryset(self, request, queryset, view):
        search_terms = self.get_search_terms(request)

        if not search_terms:
            return queryset
        base = queryset
        q1 = Q(short_name_joined__istartswith=search_terms[0])
        q2 = Q(full_name_joined__istartswith=search_terms[0])
        queryset = queryset.annotate(
            short_name_joined=Func(F('short_name'),
                                   Value(' '),
                                   Value(''),
                                   function='replace'),
            full_name_joined=Func(F('full_name'),
                                  Value(' '),
                                  Value(''),
                                  function='replace')).filter(q1 | q2)
        queryset = distinct(queryset, base)
        return queryset
示例#15
0
    def filter_queryset(self, request, queryset, view):
        """
        Prioritise the search by search fields
        """
        search_fields = getattr(view, 'search_fields', None)
        search_term = self.get_search_terms(request)

        if not search_fields or not search_term:
            return queryset

        base = queryset
        orm_lookups = [
            self.construct_search(six.text_type(search_field))
            for search_field in search_fields
        ]

        annotate_query = {}
        annotate_query_lookups = []
        for index, orm_lookup in enumerate(orm_lookups):
            annotate_query_lookups.append(f'lookup{index}')
            annotate_query.update({
                annotate_query_lookups[index]:
                Coalesce(
                    ExpressionWrapper(Q(**{orm_lookup: search_term}),
                                      output_field=BooleanField()), False)
            })

        queryset = queryset.annotate(**annotate_query).filter(
            reduce(operator.or_, [
                models.Q(**{lookup: True}) for lookup in annotate_query_lookups
            ]))

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)

        queryset = queryset.order_by(
            *[f'-{lookup}' for lookup in annotate_query_lookups])
        return queryset
示例#16
0
 def filter_search(self, queryset, value):
     search_fields = (
         "name",
         "section__name",
     )
     search_terms = value.replace(',', ' ').split()
     if not search_fields or not search_terms:
         return queryset
     orm_lookups = [
         self.construct_search(six.text_type(search_field))
         for search_field in search_fields
     ]
     base = queryset
     for search_term in search_terms:
         queries = [
             models.Q(**{orm_lookup: search_term})
             for orm_lookup in orm_lookups
         ]
         queryset = queryset.filter(reduce(operator.or_, queries))
     return distinct(queryset, base)
示例#17
0
    def filter_queryset(self, request, queryset, view):
        """This is a minor reimplementation of the filter_queryset on
        SearchFilter from DjangoRestFramework, but adds a query against the id
        if present.
        """
        search_fields = getattr(view, 'search_fields', None)
        search_terms = self.get_search_terms(request)

        # If not doing any searching, at least filter on id.
        pk = request.query_params.get('id', None)
        if not search_fields or not search_terms:
            if pk is not None:
                return queryset.filter(pk=pk)
            else:
                return queryset

        orm_lookups = [
            self.construct_search(six.text_type(search_field))
            for search_field in search_fields
        ]

        base = queryset
        for search_term in search_terms:
            queries = [
                models.Q(**{orm_lookup: search_term})
                for orm_lookup in orm_lookups
            ]
            # Always add pk as an OR match.
            if pk is not None:
                queries.append(models.Q(pk=pk))
            queryset = queryset.filter(reduce(operator.or_, queries))

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)
        return queryset
示例#18
0
    def filter_queryset(self, request, queryset, view):
        """This is a minor reimplementation of the filter_queryset on
        SearchFilter from DjangoRestFramework, but adds a query against the id
        if present.
        """
        search_fields = getattr(view, 'search_fields', None)
        search_terms = self.get_search_terms(request)

        # If not doing any searching, at least filter on id.
        pk = request.query_params.get('id', None)
        if not search_fields or not search_terms:
            if pk is not None:
                return queryset.filter(pk=pk)
            else:
                return queryset

        orm_lookups = [
            self.construct_search(six.text_type(search_field))
            for search_field in search_fields
        ]

        base = queryset
        for search_term in search_terms:
            queries = [
                models.Q(**{orm_lookup: search_term})
                for orm_lookup in orm_lookups
            ]
            # Always add pk as an OR match.
            if pk is not None:
                queries.append(models.Q(pk=pk))
            queryset = queryset.filter(reduce(operator.or_, queries))

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)
        return queryset
示例#19
0
    def filter_queryset(self, request, queryset, view):
        """Custom `filter_queryset` method.

        This is the original `filter_queryset` method with adding extra
        search conditions for ``SearchFilter`` filtering.

        """
        search_fields = getattr(view, 'search_fields', None)
        search_terms = self.get_search_terms(request)

        if not search_fields or not search_terms:
            return queryset

        orm_lookups = [
            self.construct_search(six.text_type(search_field))
            for search_field in search_fields
        ]

        base = queryset
        conditions = []

        # Here is custom code - each search term in transformed to each of
        # specified keyboard layouts

        for search_term in search_terms:
            queries = [
                models.Q(**{orm_lookup: self.get_term(search_term, layout)})
                for orm_lookup in orm_lookups
                for layout in self.get_search_layouts(view)
            ]
            conditions.append(reduce(operator.or_, queries))

        queryset = queryset.filter(reduce(operator.and_, conditions))

        if self.must_call_distinct(queryset, search_fields):
            queryset = distinct(queryset, base)

        return queryset
示例#20
0
    def filter_queryset(self, request, queryset, view):
        search_fields = self.get_search_fields(view, request)
        search_terms = self.get_search_terms(request)

        if not search_fields or not search_terms:
            return queryset

        orm_lookups = [
            self.construct_search(str(search_field))
            for search_field in search_fields
        ]

        base = queryset
        if self.required_m2m_optimization(view):
            queryset = self.optimized_queryset_filter(queryset, search_terms,
                                                      orm_lookups)
        else:
            queryset = self.chained_queryset_filter(queryset, search_terms,
                                                    orm_lookups)

        if self.must_call_distinct(queryset, search_fields):
            queryset = distinct(queryset, base)
        return queryset
示例#21
0
    def filter_queryset(self, request, queryset, view):
        search_terms = self.get_base_search_terms(request)

        # if there nothing to search - return
        if not search_terms:
            return queryset

        # first try to search in lucene way
        searchset_class = self.get_searchset_class(view, request)
        filtered_queryset = self.lucene_filter_queyset(searchset_class=searchset_class, search_terms=search_terms,
                                                       queryset=queryset)

        # if there is nothing to present
        # we give a second chance to common search
        if filtered_queryset is None:
            queryset = super().filter_queryset(request=request, queryset=queryset, view=view)
        else:
            if self.must_call_distinct(queryset, searchset_class.get_fields_sources()):
                queryset = distinct(filtered_queryset, queryset)
            else:
                queryset = filtered_queryset

        return queryset
示例#22
0
    def filter_queryset(self, query_params, queryset, service):
        """
        过滤查询集
        :param query_params: 查询参数
        :param queryset: 查询集
        :param service: 服务
        :return: 查询集
        """
        # 获取可查询的字段列表
        search_fields = self.get_search_params(service)

        if not search_fields:
            return queryset

        # 获取查询字段和输入值
        search_field_terms = self.get_search_fields_terms(
            search_fields, query_params)

        base = queryset
        conditions = []
        # 组合查询
        for search_field, search_terms in search_field_terms.items():
            orm_lookup = self.construct_search(six.text_type(search_field))
            queries = [
                models.Q(**{orm_lookup: search_term})
                for search_term in search_terms
            ]
            conditions.append(reduce(operator.or_, queries))

        if conditions:
            queryset = queryset.filter(reduce(operator.and_, conditions))

        if self.must_call_distinct(
                queryset, self.get_search_fields(service, query_params)):
            queryset = distinct(queryset, base)

        return queryset
示例#23
0
    def filter_queryset(self, request, queryset, view):
        if connection.features.has_native_uuid_field:
            return super().filter_queryset(request, queryset, view)

        search_fields = self.get_search_fields(view, request)
        search_terms = self.get_search_terms(request)

        if not search_fields or not search_terms:
            return queryset

        orm_lookups = [
            self.construct_search(str(search_field))
            for search_field in search_fields
        ]

        base = queryset
        conditions = []
        for search_term in search_terms:
            queries = []

            for orm_lookup in orm_lookups:
                search_field = orm_lookup.split(LOOKUP_SEP)[0]
                field_type = queryset.model._meta.get_field(search_field)
                if isinstance(field_type, UUIDField):
                    search_term = search_term.replace('-', '')
                queries.append(Q(**{orm_lookup: search_term}))
            conditions.append(reduce(operator.or_, queries))
        queryset = queryset.filter(reduce(operator.and_, conditions))

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)
        return queryset
示例#24
0
    def filter_queryset(self, request, queryset, view):
        search_fields = getattr(view, 'search_fields', None)
        search_terms = self.get_search_terms(request)

        if not search_fields or not search_terms:
            return queryset

        orm_lookups = [
            self.construct_search(six.text_type(search_field))
            for search_field in search_fields
        ]

        base = queryset
        conditions = []
        for search_term in search_terms:
            queries = [
                models.Q(**{orm_lookup: search_term})
                for orm_lookup in orm_lookups
            ]
            conditions.append(reduce(operator.or_, queries))
        queryset = queryset.filter(reduce(operator.and_, conditions))

        queryset = distinct(queryset, base)
        return queryset
示例#25
0
文件: django.py 项目: dimatti/lucyfer
 def _use_distinct(self, searchset_class, queryset, filtered_queryset):
     if self.must_call_distinct(queryset, searchset_class.get_fields_sources()):
         return distinct(filtered_queryset, queryset)
     else:
         return filtered_queryset
示例#26
0
    def filter_queryset(self, request, queryset, view):
        search_fields = self.get_search_fields(view, request)
        search_terms = self.get_search_terms(request)

        # print("I am in EbsSearchFilter*********************************")
        # print("search_fields type=")
        # print(type(search_fields))
        # print("search_fields=")
        # print(search_fields)

        if not search_fields or not search_terms:
            return queryset

        nested_target = list(set(search_fields) & set(self.nested_fields))
        regular_target = list(set(search_fields) - set(self.nested_fields))
        """ for test in regular_target:
            print(type(self.construct_search(test)))
            print(self.construct_search(test)) """

        orm_lookups = [
            self.construct_search(str(search_field))
            for search_field in regular_target
        ]

        nested_lookups = [
            self.construct_search(str(search_field))
            for search_field in nested_target
        ]

        base = queryset

        regular_qlist = []
        for search_term in search_terms:
            print(search_term)
            queries = [
                Q(**{orm_lookup: search_term}) for orm_lookup in orm_lookups
            ]
            regular_qlist.append(reduce(operator.or_, queries))
        regular_queryset = queryset.filter(reduce(operator.and_,
                                                  regular_qlist))

        nested_conditions = []
        for search_term in search_terms:

            nested_qlist = []
            for nested_lookup in nested_lookups:
                for nested_cat in self.nested_cats:
                    tag = nested_lookup.split("__")[0]
                    value = nested_lookup.split("__")[1]

                    d = {}
                    d[value] = search_term
                    if tag == nested_cat:
                        dd = {}
                        dd[nested_cat] = d
                        nested_qlist.append(Q(**dd))
                        #print(nested_qlist)

            # print("nested_qlist.................................")
            # print(nested_qlist)
            nested_conditions.append(reduce(operator.or_, nested_qlist))
            # print(nested_conditions)
        nested_queryset = queryset.filter(
            reduce(operator.and_, nested_conditions))
        queryset = regular_queryset | nested_queryset

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            queryset = distinct(queryset, base)
        return queryset
示例#27
0
    def filter_queryset(self, request, queryset, view):
        search_fields = getattr(view, 'search_fields', None)
        search_terms = getattr(view, 'search_words', None)
        search_terms = search_terms if search_terms else self.get_search_terms(
            request)

        if not search_fields or not search_terms:
            return queryset

        #orm_lookups = [
        #    self.construct_search(six.text_type(search_field))
        #    for search_field in search_fields
        #]
        # Add sub or operation
        orm_lookups = []
        for search_field in search_fields:
            search_field_list = search_field.split(
                settings.SEARCH_KEY_OR_DELIMITER)

            if len(search_field_list) == 1:
                # keep old
                orm_lookups.append(
                    self.construct_search(six.text_type(search_field)))
            else:
                if search_field[0] in ('$', '^', '='):
                    for i, item in enumerate(search_field_list[1:]):
                        search_field_list[
                            i + 1] = search_field[0] + search_field_list[i + 1]

                or_orm_lookups = [
                    self.construct_search(six.text_type(item))
                    for item in search_field_list
                ]
                orm_lookups.append(or_orm_lookups)

        base = queryset
        # Process for multiple search field
        if request.query_params.get(settings.SEARCH_KEY):
            for index, orm_lookup in enumerate(orm_lookups):
                try:
                    search_term = search_terms[index]
                except:
                    search_term = ''

                if isinstance(orm_lookup, list):
                    queries = [
                        models.Q(**{sub_orm_lookup: search_term})
                        for sub_orm_lookup in orm_lookup
                    ]
                else:
                    queries = [
                        models.Q(**{orm_lookup: search_term}),
                    ]

                queryset = queryset.filter(reduce(operator.or_, queries))
        else:
            # Keep full text search if not search field specified
            for search_term in search_terms:
                queries = [
                    models.Q(**{orm_lookup: search_term})
                    for orm_lookup in orm_lookups
                ]
                queryset = queryset.filter(reduce(operator.or_, queries))

        # Filtering against a many-to-many field requires us to
        # call queryset.distinct() in order to avoid duplicate items
        # in the resulting queryset.
        return distinct(queryset, base)