예제 #1
0
    def apply_nested_fields(self, data, obj):
        nested_fields_to_apply = []
        nested_fields = get_nested_fields(self.resource.schema, model_field=True)
        for key, value in data.items():
            if key in nested_fields:
                nested_field_inspection = inspect(getattr(obj.__class__, key))

                if not isinstance(nested_field_inspection, QueryableAttribute):
                    raise InvalidType("Unrecognized nested field type: not a queryable attribute.")

                if isinstance(nested_field_inspection.property, RelationshipProperty):
                    nested_model = getattr(obj.__class__, key).property.mapper.class_

                    if isinstance(value, list):
                        nested_objects = []

                        for identifier in value:
                            nested_object = nested_model(**identifier)
                            nested_objects.append(nested_object)

                        nested_fields_to_apply.append({'field': key, 'value': nested_objects})
                    else:
                        nested_fields_to_apply.append({'field': key, 'value': nested_model(**value)})
                elif isinstance(nested_field_inspection.property, ColumnProperty):
                    nested_fields_to_apply.append({'field': key, 'value': value})
                else:
                    raise InvalidType("Unrecognized nested field type: not a RelationshipProperty or ColumnProperty.")

        for nested_field in nested_fields_to_apply:
            setattr(obj, nested_field['field'], nested_field['value'])
예제 #2
0
    def create_object(self, data, view_kwargs):
        """Create an object through sqlalchemy

        :param dict data: the data validated by marshmallow
        :param dict view_kwargs: kwargs from the resource view
        :return DeclarativeMeta: an object from sqlalchemy
        """
        self.before_create_object(data, view_kwargs)

        relationship_fields = get_relationships(self.resource.schema, model_field=True)
        nested_fields = get_nested_fields(self.resource.schema, model_field=True)

        join_fields = relationship_fields + nested_fields

        obj = self.model(**{key: value
                            for (key, value) in data.items() if key not in join_fields})
        self.apply_relationships(data, obj)
        self.apply_nested_fields(data, obj)

        self.session.add(obj)
        try:
            self.session.commit()
        except JsonApiException as e:
            try:
                self.session.rollback()
            except Exception as e:
                print 'Rollback failed {}'.format(e)

            raise e

        self.after_create_object(obj, data, view_kwargs)

        return obj
예제 #3
0
    def update_object(self, obj, data, view_kwargs):
        """Update an object through sqlalchemy

        :param DeclarativeMeta obj: an object from sqlalchemy
        :param dict data: the data validated by marshmallow
        :param dict view_kwargs: kwargs from the resource view
        :return boolean: True if object have changed else False
        """
        if obj is None:
            url_field = getattr(self, 'url_field', 'id')
            filter_value = view_kwargs[url_field]
            raise ObjectNotFound('{}: {} not found'.format(self.model.__name__, filter_value),
                                 source={'parameter': url_field})

        self.before_update_object(obj, data, view_kwargs)

        relationship_fields = get_relationships(self.resource.schema, model_field=True)
        nested_fields = get_nested_fields(self.resource.schema, model_field=True)

        join_fields = relationship_fields + nested_fields

        for key, value in data.items():
            if hasattr(obj, key) and key not in join_fields:
                setattr(obj, key, value)

        self.apply_relationships(data, obj)
        self.apply_nested_fields(data, obj)

        try:
            self.session.commit()
        except JsonApiException as e:
            self.session.rollback()
            raise e

        self.after_update_object(obj, data, view_kwargs)
예제 #4
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__
예제 #5
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_