Ejemplo n.º 1
0
    def column(self):
        """Get the column object

        :param DeclarativeMeta model: the model
        :param str field: the field
        :return InstrumentedAttribute: the column to filter on
        """
        field = self.name

        model_field = get_model_field(self.schema, field)

        try:
            attr = getattr(self.model, model_field)
        except AttributeError:
            raise InvalidFilters("{} has no attribute {}".format(
                self.model.__name__, model_field))

        name = self.filter_.get('name')
        if '[' in name:
            if not isinstance(attr.type, Indexable):
                raise InvalidFilters(
                    "{} is not an indexable column".format(model_field))
            name = name[name.index('['):]
            while name.startswith('['):
                item, name = name[1:].split(']', 1)
                try:
                    item = json.loads(item)
                except json.decoder.JSONDecodeError:
                    raise InvalidFilters(
                        "{} is not a valid index".format(item))
                try:
                    attr = attr[item]
                except Exception:
                    raise InvalidFilters(
                        "{} is not a valid indexing expression".format(
                            self.filter_.get('name')))
            if name == ".as_string()":
                attr = attr.as_string()
            elif name == ".as_integer()":
                attr = attr.as_integer()
            elif name == ".as_float()":
                attr = attr.as_float()
            elif name == ".as_boolean()":
                attr = attr.as_boolean()
            elif len(name) > 0:
                raise InvalidFilters(
                    "{} is not a valid indexing expression".format(
                        self.filter_.get('name')))

        return attr
Ejemplo n.º 2
0
    def resolve(self):
        if 'or' not in self.filter_ and 'and' not in self.filter_:
            if self.val is None and self.field is None:
                raise InvalidFilters("Can't find value or field in a filter")

            value = self.value

            if isinstance(self.val, dict):
                value = Node(self.related_model, self.val, self.opts, self.related_schema).resolve()

            if '__' in self.filter_.get('name', ''):
                value = self.value
                value = {self.filter_['name'].split('__')[1]: value}

            if isinstance(value, dict):
                return getattr(self.column, self.operator)(**value)
            else:
                return getattr(self.column, self.operator)(value)

        if 'or' in self.filter_:
            return or_(Node(self.model, filt, self.opts, self.schema).resolve() for filt in self.filter_['or'])
        if 'and' in self.filter_:
            return and_(Node(self.model, filt, self.opts, self.schema).resolve() for filt in self.filter_['and'])
        if 'not' in self.filter_:
            return not_(Node(self.model, self.filter_['not'], self.opts, self.schema).resolve())
Ejemplo n.º 3
0
    def name(self):
        """Return the name of the node or raise a BadRequest exception

        :return str: the name of the field to filter on
        """
        name = self.filter_.get('name')

        if name is None:
            raise InvalidFilters("Can't find name of a filter")

        if '__' in name:
            name = name.split('__')[0]

        if name not in self.schema._declared_fields:
            raise InvalidFilters("{} has no attribut {}".format(self.schema.__name__, name))

        return name
Ejemplo n.º 4
0
    def op(self):
        """Return the operator of the node

        :return str: the operator to use in the filter
        """
        try:
            return self.filter_['op']
        except KeyError:
            raise InvalidFilters("Can't find op of a filter")
Ejemplo n.º 5
0
    def value(self):
        """Get the value to filter on

        :return: the value to filter on
        """
        if self.filter_.get('field') is not None:
            try:
                result = getattr(self.model, self.filter_['field'])
            except AttributeError:
                raise InvalidFilters("{} has no attribute {}".format(
                    self.model.__name__, self.filter_['field']))
            else:
                return result
        else:
            if 'val' not in self.filter_:
                raise InvalidFilters("Can't find value or field in a filter")

            return self.filter_['val']
Ejemplo n.º 6
0
    def related_schema(self):
        """Get the related schema of a relationship field

        :return Schema: the related schema
        """
        relationship_field = self.name

        if relationship_field not in get_relationships(self.schema):
            raise InvalidFilters("{} has no relationship attribut {}".format(self.schema.__name__, relationship_field))

        return self.schema._declared_fields[relationship_field].schema.__class__
Ejemplo n.º 7
0
    def value(self):
        """Get the value to filter on

        :return: the value to filter on
        """
        if self.field is not None:
            try:
                return getattr(self.model, self.field)
            except AttributeError:
                raise InvalidFilters("{} has no attribute {} in a filter".format(self.model.__name__, self.field))

        return self.val
Ejemplo n.º 8
0
    def operator(self):
        """Get the function operator from his name

        :return callable: a callable to make operation on a column
        """
        operators = (self.op, self.op + '_', '__' + self.op + '__')

        for op in operators:
            if hasattr(self.column, op):
                return op

        raise InvalidFilters("{} has no operator {} in a filter".format(self.column.key, self.op))
Ejemplo n.º 9
0
    def filters(self):
        """Return filters from query string.

        :return list: filter information
        """
        filters = self.qs.get('filter')
        if filters is not None:
            try:
                filters = json.loads(filters)
            except (ValueError, TypeError):
                raise InvalidFilters("Parse error")

        return filters
Ejemplo n.º 10
0
    def related_model(self):
        """Get the related model of a relationship field

        :return DeclarativeMeta: the related model
        """
        relationship_field = self.name

        if relationship_field not in get_relationships(self.schema):
            raise InvalidFilters("{} has no relationship attribut {}".format(self.schema.__name__, relationship_field))

        if hasattr(self.opts, 'schema_to_model') and self.opts.schema_to_model.get(relationship_field) is not None:
            relationship_field = self.opts.schema_to_model[relationship_field]

        return getattr(self.model, relationship_field).property.mapper.class_
Ejemplo n.º 11
0
    def filters(self):
        """Return filters from query string.

        :return list: filter information
        """
        results = []
        filters = self.qs.get('filter')
        if filters is not None:
            try:
                results.extend(json.loads(filters))
            except (ValueError, TypeError):
                raise InvalidFilters("Parse error")
        if self._get_key_values('filter['):
            results.extend(self._simple_filters(self._get_key_values('filter[')))
        return results
Ejemplo n.º 12
0
    def related_model(self):
        """Get the related model of a relationship field

        :return DeclarativeMeta: the related model
        """
        relationship_field = self.name

        if relationship_field not in get_relationships(self.schema):
            raise InvalidFilters("{} has no relationship attribute {}".format(
                self.schema.__name__, relationship_field))

        return getattr(self.model,
                       get_model_field(
                           self.schema,
                           relationship_field)).property.mapper.class_
Ejemplo n.º 13
0
    def related_schema(self):
        """Get the related schema of a related (relationship or nested) field

        :return Schema: the related schema
        """
        related_field_name = self.name
        related_fields = get_relationships(self.schema) + get_nested_fields(
            self.schema)
        if related_field_name not in related_fields:
            raise InvalidFilters(
                "{} has no relationship or nested attribute {}".format(
                    self.schema.__name__, related_field_name))

        return self.schema._declared_fields[
            related_field_name].schema.__class__
Ejemplo n.º 14
0
    def column(self):
        """Get the column object

        :param DeclarativeMeta model: the model
        :param str field: the field
        :return InstrumentedAttribute: the column to filter on
        """
        field = self.name

        model_field = get_model_field(self.schema, field)

        try:
            return getattr(self.model, model_field)
        except AttributeError:
            raise InvalidFilters("{} has no attribute {}".format(
                self.model.__name__, model_field))
Ejemplo n.º 15
0
    def column(self):
        """Get the column object

        :param DeclarativeMeta model: the model
        :param str field: the field
        :return InstrumentedAttribute: the column to filter on
        """
        field = self.name

        if self.schema._declared_fields[field].attribute is not None:
            field = self.schema._declared_fields[field].attribute

        try:
            return getattr(self.model, field)
        except AttributeError:
            raise InvalidFilters("{} has no attribute {} in a filter".format(self.model.__name__, field))
Ejemplo n.º 16
0
    def related_model(self):
        """Get the related model of a related (relationship or nested) field

        :return DeclarativeMeta: the related model
        """
        related_field_name = self.name

        related_fields = get_relationships(self.schema) + get_nested_fields(
            self.schema)
        if related_field_name not in related_fields:
            raise InvalidFilters(
                "{} has no relationship or nested attribute {}".format(
                    self.schema.__name__, related_field_name))

        return getattr(self.model,
                       get_model_field(
                           self.schema,
                           related_field_name)).property.mapper.class_