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