Exemplo n.º 1
0
    def get_relationship(self, relationship_field, related_type_, related_id_field, view_kwargs):
        """Get a relationship

        :param str relationship_field: the model attribute used for relationship
        :param str related_type_: the related resource type
        :param str related_id_field: the identifier field of the related model
        :param dict view_kwargs: kwargs from the resource view
        :return tuple: the object and related object(s)
        """
        self.before_get_relationship(relationship_field, related_type_, related_id_field, view_kwargs)

        obj = self.get_object(view_kwargs)

        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})

        if not hasattr(obj, relationship_field):
            raise RelationNotFound("{} has no attribute {}".format(obj.__class__.__name__, relationship_field))

        related_objects = getattr(obj, relationship_field)

        if related_objects is None:
            return obj, related_objects

        self.after_get_relationship(obj, related_objects, relationship_field, related_type_, related_id_field,
                                    view_kwargs)

        if isinstance(related_objects, InstrumentedList):
            return obj,\
                [{'type': related_type_, 'id': getattr(obj_, related_id_field)} for obj_ in related_objects]
        else:
            return obj, {'type': related_type_, 'id': getattr(related_objects, related_id_field)}
Exemplo n.º 2
0
    def delete_relationship(self, json_data, relationship_field,
                            related_id_field, view_kwargs):
        """Delete a relationship

        :param dict json_data: the request params
        :param str relationship_field: the model attribute used for relationship
        :param str related_id_field: the identifier field of the related model
        :param dict view_kwargs: kwargs from the resource view
        """
        self.before_delete_relationship(json_data, relationship_field,
                                        related_id_field, view_kwargs)

        obj = self.get_object(view_kwargs)

        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})

        if not hasattr(obj, relationship_field):
            raise RelationNotFound("{} has no attribute {}".format(
                obj.__class__.__name__, relationship_field))

        related_model = getattr(obj.__class__,
                                relationship_field).property.mapper.class_

        updated = False

        if isinstance(json_data['data'], list):
            obj_ids = {
                str(getattr(obj__, related_id_field))
                for obj__ in getattr(obj, relationship_field)
            }

            for obj_ in json_data['data']:
                if obj_['id'] in obj_ids:
                    getattr(obj, relationship_field).remove(
                        self.get_related_object(related_model,
                                                related_id_field, obj_))
                    updated = True
        else:
            setattr(obj, relationship_field, None)
            updated = True

        try:
            self.session.commit()
        except JsonApiException as e:
            self.session.rollback()
            raise e
        except Exception as e:
            self.session.rollback()
            raise JsonApiException("Delete relationship error: " + str(e))

        self.after_delete_relationship(obj, updated, json_data,
                                       relationship_field, related_id_field,
                                       view_kwargs)

        return obj, updated
Exemplo n.º 3
0
    def get_relationship(self, relationship_field, related_type_,
                         related_id_field, **view_kwargs):
        """Get a relationship

        :param str relationship_field: the model attribut used for relationship
        :param str related_type_: the related resource type
        :param str related_id_field: the identifier field of the related model
        :param dict view_kwargs: kwargs from the resource view
        :return tuple: the object and related object(s)
        """
        obj = self.get_object(**view_kwargs)

        if not hasattr(obj, relationship_field):
            raise RelationNotFound(
                '', "{} has no attribut {}".format(obj.__class__.__name__,
                                                   relationship_field))

        related_objects = getattr(obj, relationship_field)

        if related_objects is None:
            return obj, related_objects

        if isinstance(related_objects, InstrumentedList):
            return obj,\
                [{'type': related_type_, 'id': getattr(obj_, related_id_field)} for obj_ in related_objects]
        else:
            return obj, {
                'type': related_type_,
                'id': getattr(related_objects, related_id_field)
            }
Exemplo n.º 4
0
    def update_relationship(self, json_data, relationship_field, related_id_field, view_kwargs):
        """Update a relationship

        :param dict json_data: the request params
        :param str relationship_field: the model attribute used for relationship
        :param str related_id_field: the identifier field of the related model
        :param dict view_kwargs: kwargs from the resource view
        :return boolean: True if relationship have changed else False
        """
        self.before_update_relationship(json_data, relationship_field, related_id_field, view_kwargs)

        obj = self.get_object(view_kwargs)

        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})

        if not hasattr(obj, relationship_field):
            raise RelationNotFound("{} has no attribute {}".format(obj.__class__.__name__, relationship_field))

        related_model = getattr(obj.__class__, relationship_field).property.mapper.class_

        updated = False

        if isinstance(json_data['data'], list):
            related_objects = []

            for obj_ in json_data['data']:
                related_objects.append(self.get_related_object(related_model, related_id_field, obj_))

            obj_ids = {getattr(obj__, related_id_field) for obj__ in getattr(obj, relationship_field)}
            new_obj_ids = {getattr(related_object, related_id_field) for related_object in related_objects}
            if obj_ids != new_obj_ids:
                setattr(obj, relationship_field, related_objects)
                updated = True

        else:
            related_object = None

            if json_data['data'] is not None:
                related_object = self.get_related_object(related_model, related_id_field, json_data['data'])

            obj_id = getattr(getattr(obj, relationship_field), related_id_field, None)
            new_obj_id = getattr(related_object, related_id_field, None)
            if obj_id != new_obj_id:
                setattr(obj, relationship_field, related_object)
                updated = True

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

        self.after_update_relationship(obj, updated, json_data, relationship_field, related_id_field, view_kwargs)

        return obj, updated
Exemplo n.º 5
0
    def create_relationship(self, json_data, relationship_field,
                            related_id_field, **view_kwargs):
        """Create a relationship

        :param dict json_data: the request params
        :param str relationship_field: the model attribut used for relationship
        :param str related_id_field: the identifier field of the related model
        :param dict view_kwargs: kwargs from the resource view
        :return boolean: True if relationship have changed else False
        """
        obj = self.get_object(**view_kwargs)

        if not hasattr(obj, relationship_field):
            raise RelationNotFound(
                '', "{} has no attribut {}".format(obj.__class__.__name__,
                                                   relationship_field))

        related_model = getattr(obj.__class__,
                                relationship_field).property.mapper.class_

        updated = False

        if isinstance(json_data['data'], list):
            obj_ids = {
                str(getattr(obj__, related_id_field))
                for obj__ in getattr(obj, relationship_field)
            }

            for obj_ in json_data['data']:
                if obj_['id'] not in obj_ids:
                    getattr(obj, relationship_field).append(
                        self.get_related_object(related_model,
                                                related_id_field, obj_))
                    updated = True
        else:
            related_object = None

            if json_data['data'] is not None:
                related_object = self.get_related_object(
                    related_model, related_id_field, json_data['data'])

            obj_id = getattr(getattr(obj, relationship_field),
                             related_id_field, None)
            new_obj_id = getattr(related_object, related_id_field, None)
            if obj_id != new_obj_id:
                setattr(obj, relationship_field, related_object)
                updated = True

        try:
            self.session.commit()
        except Exception as e:
            self.session.rollback()
            raise JsonApiException('', "Create relationship error: " + str(e))

        return obj, updated
Exemplo n.º 6
0
    def _get_relationship_data(self):
        """Get useful data for relationship management"""
        relationship_field = request.path.split('/')[-1]

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

        related_type_ = self.schema._declared_fields[relationship_field].type_
        related_id_field = self.schema._declared_fields[relationship_field].id_field
        model_relationship_field = get_model_field(self.schema, relationship_field)

        return relationship_field, model_relationship_field, related_type_, related_id_field
Exemplo n.º 7
0
    def _get_relationship_data(self):
        """Get useful data for relationship management
        """
        relationship_field = request.base_url.split('/')[-1]

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

        related_type_ = self.schema._declared_fields[relationship_field].type_
        related_id_field = self.schema._declared_fields[relationship_field].id_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 relationship_field, related_type_, related_id_field