def test_searching_q_ok(value, db_lookup, db_value):
    cls = BooksFilterClass(book_qs)

    for v in (value, '"{}"'.format(value)):
        like_q = cls.build_q_for_filter(FilterArgs('title', SearchOperators.LIKE, v))
        assert like_q.children[0] == ('title__{}'.format(db_lookup), db_value)

    i_like_q = cls.build_q_for_filter(FilterArgs('title', SearchOperators.I_LIKE, value))
    assert i_like_q.children[0] == ('title__i{}'.format(db_lookup), db_value)
    def listing(self, args):
        # Django __in lookup is not used, because of null() values
        operation, prop = self._get_value(args[0]), self._get_value(args[1])
        f_op = ComparisonOperators.EQ if operation == ListOperators.IN else ComparisonOperators.NE

        q = Q()
        for value_tree in args[2:]:
            value = self._get_value(value_tree)
            if isinstance(value, Q):
                if f_op == ComparisonOperators.EQ:
                    field_q = value
                else:
                    field_q = ~value
            else:
                field_q = self._filter_cls_instance.build_q_for_filter(
                    FilterArgs(
                        prop,
                        f_op,
                        value,
                        list_operator=operation,
                    ))
            if operation == ListOperators.IN:
                q |= field_q
            else:
                q &= field_q

        self._filtered_props.add(prop)

        return q
Exemple #3
0
    def _build_q_for_search(self, operator, str_value):
        if operator != ComparisonOperators.EQ:
            raise RQLFilterParsingError(
                details={
                    'error': 'Bad search filter: {}.'.format(operator),
                })

        unquoted_value = self.remove_quotes(str_value)
        if not unquoted_value:
            return Q()

        if not unquoted_value.startswith(RQL_ANY_SYMBOL):
            unquoted_value = '*' + unquoted_value

        if not unquoted_value.endswith(RQL_ANY_SYMBOL):
            unquoted_value += '*'

        q = self._build_q_for_extended_search(unquoted_value)
        for filter_name in self.search_filters:
            q |= self.build_q_for_filter(
                FilterArgs(
                    filter_name,
                    SearchOperators.I_LIKE,
                    unquoted_value,
                ))

        return q
Exemple #4
0
    def searching(self, args):
        # like, ilike
        operation, prop, val = tuple(
            self._get_value(args[index]) for index in range(3))
        self._filtered_props.add(prop)

        return self._filter_cls_instance.build_q_for_filter(
            FilterArgs(prop, operation, val))
def test_custom_filter_ok():
    class CustomCls(BooksFilterClass):
        def build_q_for_custom_filter(self, *args, **kwargs):
            return Q(id__gte=2)

    filter_cls = CustomCls(book_qs)
    q = filter_cls.build_q_for_filter(FilterArgs('custom_filter', SearchOperators.I_LIKE, 'value'))

    books = [Book.objects.create() for _ in range(2)]
    assert list(book_qs.filter(q)) == [books[1]]
 def searching(self, args):
     # like, ilike
     operation, prop, val = tuple(
         self._get_value(args[index]) for index in range(3))
     filter_args = FilterArgs(prop,
                              operation,
                              val,
                              namespace=self._get_current_namespace())
     self._filtered_props.add(filter_args.filter_name)
     return self._filter_cls_instance.build_q_for_filter(filter_args)
    def comp(self, args):
        prop, operation, value = self._extract_comparison(args)

        if isinstance(value, Q):
            if operation == ComparisonOperators.EQ:
                return value
            else:
                return ~value

        filter_args = FilterArgs(prop,
                                 operation,
                                 value,
                                 namespace=self._get_current_namespace())
        self._filtered_props.add(filter_args.filter_name)
        return self._filter_cls_instance.build_q_for_filter(filter_args)
Exemple #8
0
def filter_field(filter_name, operator, value):
    filter_cls = BooksFilterClass(book_qs)
    q = filter_cls.build_q_for_filter(
        FilterArgs(filter_name, operator, str(value)))
    return list(book_qs.filter(q))
Exemple #9
0
    def build_q_for_filter(self, data):
        """ Django Q() builder for extracted from query RQL expression.
        In general, this method should not be overridden.

        :param FilterArgs data: Prepared filter data for custom filtering.
        :rtype: django.db.models.Q
        """
        filter_name, operator, str_value = data.filter_name, data.operator, data.str_value
        list_operator = data.list_operator

        if filter_name == RQL_SEARCH_PARAM:
            return self._build_q_for_search(operator, str_value)

        base_item = self.get_filter_base_item(filter_name)
        if not base_item:
            return Q()

        if base_item.get('distinct'):
            self._is_distinct = True

        filter_item = self.filters[filter_name]
        available_lookups = base_item.get('lookups', set())
        if list_operator:
            list_filter_lookup = FilterLookups.IN \
                if list_operator == ListOperators.IN \
                else FilterLookups.OUT
            if list_filter_lookup not in available_lookups:
                raise RQLFilterLookupError(**self._get_error_details(
                    filter_name,
                    list_filter_lookup,
                    str_value,
                ))

        null_values = base_item.get('null_values', set())
        filter_lookup = self._get_filter_lookup(
            filter_name,
            operator,
            str_value,
            available_lookups,
            null_values,
        )
        django_lookup = self._get_django_lookup(filter_lookup, str_value,
                                                null_values)

        if base_item.get('custom'):
            return self.build_q_for_custom_filter(
                FilterArgs(
                    filter_name,
                    operator,
                    str_value,
                    list_operator=list_operator,
                    filter_lookup=filter_lookup,
                    django_lookup=django_lookup,
                ))

        django_field = base_item['field']
        use_repr = base_item.get('use_repr', False)

        typed_value = self._get_typed_value(
            filter_name,
            filter_lookup,
            str_value,
            django_field,
            use_repr,
            null_values,
            django_lookup,
        )

        if not isinstance(filter_item, iterable_types):
            return self._build_django_q(filter_item, django_lookup,
                                        filter_lookup, typed_value)

        # filter has different DB field 'sources'
        q = Q()
        for item in filter_item:
            item_q = self._build_django_q(item, django_lookup, filter_lookup,
                                          typed_value)
            if filter_lookup == FilterLookups.NE:
                q &= item_q
            else:
                q |= item_q
        return q
Exemple #10
0
    def comp(self, args):
        prop, operation, value = self._extract_comparison(args)
        self._filtered_props.add(prop)

        return self._filter_cls_instance.build_q_for_filter(
            FilterArgs(prop, operation, value))