def create_ilike_filter(column, value): value = maybe_unicode(value) if value: words = value.split() if words: like_str = u('%%%s%%') % '%'.join(clean_unicode(w) for w in words) column = postgresql_non_ascii_and_lower(column) return column.ilike(like_str.lower())
def create_global_search_options(self, search, tables): response = [] search = clean_unicode(search) search_list = search.split() for table in maybe_list(tables): ignore_columns = getattr(table, '__ignore_on_global_search__', None) ignore_ids = getattr(table, '__ignore_ids_on_global_search__', True) for column_name in table._sa_class_manager.local_attrs.keys(): if ((ignore_ids and (column_name == 'id' or column_name.endswith('_id'))) or (ignore_columns and column_name in ignore_columns)): continue column = getattr(table, column_name) if hasattr(column, 'type'): if isinstance(column.type, Enum): for value in column.type.enums: value_to_search = value for s in search_list: try: idx = value_to_search.index(s) except ValueError: break else: value_to_search = value_to_search[idx + len(s):] else: response.append(column == value) elif isinstance(column.type, String): value = create_like_filter(column, search) if value is not None: response.append(value) elif isinstance(column.type, (Numeric, Integer, Date, DateTime)): value = create_like_filter(cast(column, String), search) if value is not None: response.append(value) else: clauses = getattr(column, 'clauses', None) if clauses is not None: value = create_like_filter(func.concat(*clauses), search) if value is not None: response.append(value) else: value = create_like_filter(cast(column, String), search) if value is not None: response.append(value) return response
def do_filter_by(response, key, values, clear_response=True): keep_index = set() if isinstance(values, FilterBy): filter_type = values.filter_type.lower() if filter_type == 'or': for value in values.value: keep_index.update(do_filter_by(response, key, value, clear_response=False)) elif filter_type == 'and': valid_response = list(response) for value in values.value: valid_index = do_filter_by(valid_response, key, value, clear_response=False) if not valid_index: valid_response.clear() else: for i in reversed(list(enumerate(valid_response))): if i not in valid_index: valid_response.pop(i) if not valid_response: break keep_index.update(i for i, r in enumerate(valid_response)) elif filter_type in ('like', 'contém'): values = [clean_unicode(v).lower() for v in values.value.split()] for i, r in enumerate(response): r_value = r.get(key) if not r_value: continue r_value = clean_unicode(r_value).lower() for value in values: try: ridx = r_value.index(value) except ValueError: break else: r_value = r_value[ridx + len(value):] else: keep_index.add(i) elif filter_type == '>': keep_index.update( i for i, r in enumerate(response) if compare_values(r.get(key), values.value, '__gt__')) elif filter_type == '>=': keep_index.update( i for i, r in enumerate(response) if compare_values(r.get(key), values.value, '__ge__')) elif filter_type == '<': keep_index.update( i for i, r in enumerate(response) if compare_values(r.get(key), values.value, '__lt__')) elif filter_type == '<=': keep_index.update( i for i, r in enumerate(response) if compare_values(r.get(key), values.value, '__le__')) elif filter_type in ('=', '=='): keep_index.update( i for i, r in enumerate(response) if compare_values(r.get(key), values.value, '__eq__')) elif filter_type in ('!=', '≠'): keep_index.update( i for i, r in enumerate(response) if compare_values(r.get(key), values.value, '__ne__')) else: raise Error('filter_type', u('Invalid filter type %s') % values.filter_type) elif values is drop: pass elif not is_nonstr_iter(values): keep_index.update( i for i, r in enumerate(response) if r.get(key) == values) else: for value in values: if isinstance(value, FilterBy) or is_nonstr_iter(value): keep_index.update(do_filter_by(response, key, value, clear_response=False)) elif value is not drop: keep_index.update( i for i, r in enumerate(response) if compare_values(r.get(key), value, '__eq__')) if not clear_response: return keep_index elif not keep_index: response.clear() else: for i, r in reversed(list(enumerate(response))): if i not in keep_index: response.pop(i)