예제 #1
0
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())
예제 #2
0
    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
예제 #3
0
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)