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