def _delete_many(cls, items, request=None, synchronize_session=False): """ Delete :items: queryset or objects list. When queryset passed, Query.delete() is used to delete it but first queryset is re-queried to clean it from explicit limit/offset/etc. If some of the methods listed above were called, or :items: is not a Query instance, one-by-one items update is performed. `on_bulk_delete` function is called to delete objects from index and to reindex relationships. This is done explicitly because it is impossible to get access to deleted objects in signal handler for 'after_bulk_delete' ORM event. """ if isinstance(items, Query): del_queryset = cls._clean_queryset(items) del_items = del_queryset.all() del_count = del_queryset.delete( synchronize_session=synchronize_session) on_bulk_delete(cls, del_items, request) return del_count items_count = len(items) session = Session() for item in items: item._request = request session.delete(item) session.flush() return items_count
def filter_objects(cls, objects, first=False, **params): """ Perform query with :params: on instances sequence :objects: :param object: Sequence of :cls: instances on which query should be run. :param params: Query parameters to filter :objects:. """ id_name = cls.pk_field() ids = [getattr(obj, id_name, None) for obj in objects] ids = [str(id_) for id_ in ids if id_ is not None] field_obj = getattr(cls, id_name) query_set = Session().query(cls).filter(field_obj.in_(ids)) if params: params['query_set'] = query_set.from_self() query_set = cls.get_collection(**params) if first: first_obj = query_set.first() if not first_obj: msg = "'{}({})' resource not found".format( cls.__name__, params) raise JHTTPNotFound(msg) return first_obj return query_set
def save(self, *arg, **kw): session = object_session(self) self._bump_version() session = session or Session() try: session.add(self) session.flush() return self except (IntegrityError,) as e: if 'duplicate' not in e.message: raise # Other error, not duplicate raise JHTTPConflict( detail='Resource `%s` already exists.' % self.__class__.__name__, extra={'data': e})
def save(self, request=None): session = object_session(self) self._request = request session = session or Session() try: session.add(self) session.flush() session.expire(self) return self except (IntegrityError, ) as e: if 'duplicate' not in e.args[0]: raise # Other error, not duplicate raise JHTTPConflict(detail='Resource `{}` already exists.'.format( self.__class__.__name__), extra={'data': e})
def post(self, schema, data): # # ファイルアップロード用のスキーマ # form = Form(data, schema=schema) if form.validate(): # # トランザクションの開始 # with transaction.manager: # # セッションの作成 # session = Session() # # ファイル名、ファイルのデータ取得 # storage = form.request.params.getone('file') model = self._Model(**{ 'name': storage.filename, 'data': storage.file.read(), }) # # セッションに要素の追加 # session.add(model) # # 登録 # session.flush() # # 辞書として返す # return model.to_dict() # # 失敗した場合の処理 # return HTTPNotFound()
def __init__(self, idmap, model): # # モデル型の中から ID で指定された要素を検索 # self._query = Session().query(model) self._filtered_query = self._query.filter_by(**idmap)
def get_collection(cls, **params): """ Query collection and return results. Notes: * Before validating that only model fields are present in params, reserved params, query params and all params starting with double underscore are dropped. * Params which have value "_all" are dropped. * When ``_count`` param is used, objects count is returned before applying offset and limit. :param bool _strict: If True ``params`` are validated to contain only fields defined on model, exception is raised if invalid fields are present. When False - invalid fields are dropped. Defaults to ``True``. :param bool _item_request: Indicates whether it is a single item request or not. When True and DataError happens on DB request, JHTTPNotFound is raised. JHTTPBadRequest is raised when False. Defaults to ``False``. :param list _sort: Field names to sort results by. If field name is prefixed with "-" it is used for "descending" sorting. Otherwise "ascending" sorting is performed by that field. Defaults to an empty list in which case sorting is not performed. :param list _fields: Names of fields which should be included or excluded from results. Fields to excluded should be prefixed with "-". Defaults to an empty list in which case all fields are returned. :param int _limit: Number of results per page. Defaults to None in which case all results are returned. :param int _page: Number of page. In conjunction with ``_limit`` is used to calculate results offset. Defaults to None in which case it is ignored. Params ``_page`` and ``_start` are mutually exclusive. :param int _start: Results offset. If provided ``_limit`` and ``_page`` params are ignored when calculating offset. Defaults to None. Params ``_page`` and ``_start`` are mutually exclusive. If not offset-related params are provided, offset equals to 0. :param Query query_set: Existing queryset. If provided, all queries are applied to it instead of creating new queryset. Defaults to None. :param _count: When provided, only results number is returned as integer. :param _explain: When provided, query performed(SQL) is returned as a string instead of query results. :param bool _raise_on_empty: When True JHTTPNotFound is raised if query returned no results. Defaults to False in which case error is just logged and empty query results are returned. :returns: Query results as ``sqlalchemy.orm.query.Query`` instance. May be sorted, offset, limited. :returns: Dict of {'field_name': fieldval}, when ``_fields`` param is provided. :returns: Number of query results as an int when ``_count`` param is provided. :returns: String representing query ran when ``_explain`` param is provided. :raises JHTTPNotFound: When ``_raise_on_empty=True`` and no results found. :raises JHTTPNotFound: When ``_item_request=True`` and ``sqlalchemy.exc.DataError`` exception is raised during DB query. Latter exception is raised when querying DB with an identifier of a wrong type. E.g. when querying Int field with a string. :raises JHTTPBadRequest: When ``_item_request=False`` and ``sqlalchemy.exc.DataError`` exception is raised during DB query. :raises JHTTPBadRequest: When ``sqlalchemy.exc.InvalidRequestError`` or ``sqlalchemy.exc.IntegrityError`` errors happen during DB query. """ log.debug('Get collection: {}, {}'.format(cls.__name__, params)) params.pop('__confirmation', False) _strict = params.pop('_strict', True) _item_request = params.pop('_item_request', False) _sort = _split(params.pop('_sort', [])) _fields = _split(params.pop('_fields', [])) _limit = params.pop('_limit', None) _page = params.pop('_page', None) _start = params.pop('_start', None) query_set = params.pop('query_set', None) _count = '_count' in params params.pop('_count', None) _explain = '_explain' in params params.pop('_explain', None) _raise_on_empty = params.pop('_raise_on_empty', False) if query_set is None: query_set = Session().query(cls) # Remove any __ legacy instructions from this point on params = dictset({ key: val for key, val in params.items() if not key.startswith('__') }) iterables_exprs, params = cls._pop_iterables(params) params = drop_reserved_params(params) if _strict: _check_fields = [ f.strip('-+') for f in list(params.keys()) + _fields + _sort ] cls.check_fields_allowed(_check_fields) else: params = cls.filter_fields(params) process_lists(params) process_bools(params) # If param is _all then remove it params.pop_by_values('_all') try: query_set = query_set.filter_by(**params) # Apply filtering by iterable expressions for expr in iterables_exprs: query_set = query_set.from_self().filter(expr) _total = query_set.count() if _count: return _total # Filtering by fields has to be the first thing to do on # the query_set! query_set = cls.apply_fields(query_set, _fields) query_set = cls.apply_sort(query_set, _sort) if _limit is not None: _start, _limit = process_limit(_start, _page, _limit) query_set = query_set.offset(_start).limit(_limit) if not query_set.count(): msg = "'%s(%s)' resource not found" % (cls.__name__, params) if _raise_on_empty: raise JHTTPNotFound(msg) else: log.debug(msg) except DataError as ex: if _item_request: msg = "'{}({})' resource not found".format( cls.__name__, params) raise JHTTPNotFound(msg, explanation=ex.message) else: raise JHTTPBadRequest(str(ex), extra={'data': ex}) except (InvalidRequestError, ) as ex: raise JHTTPBadRequest(str(ex), extra={'data': ex}) query_sql = str(query_set).replace('\n', '') if _explain: return query_sql log.debug('get_collection.query_set: %s (%s)', cls.__name__, query_sql) if _fields: query_set = cls.add_field_names(query_set, _fields) query_set._nefertari_meta = dict(total=_total, start=_start, fields=_fields) return query_set
def _delete_many(cls, items): session = Session() for item in items: session.delete(item) session.flush()
def get_collection(cls, **params): """ params may include '_limit', '_page', '_sort', '_fields' returns paginated and sorted query set raises JHTTPBadRequest for bad values in params """ params.pop('__confirmation', False) __strict = params.pop('__strict', True) _sort = _split(params.pop('_sort', [])) _fields = _split(params.pop('_fields', [])) _limit = params.pop('_limit', None) _page = params.pop('_page', None) _start = params.pop('_start', None) _count = '_count' in params; params.pop('_count', None) _explain = '_explain' in params; params.pop('_explain', None) __raise_on_empty = params.pop('__raise_on_empty', False) session = Session() # Remove any __ legacy instructions from this point on params = dictset(filter(lambda item: not item[0].startswith('__'), params.items())) if __strict: _check_fields = [f.strip('-+') for f in params.keys() + _fields + _sort] cls.check_fields_allowed(_check_fields) else: params = cls.filter_fields(params) process_lists(params) process_bools(params) # If param is _all then remove it params.pop_by_values('_all') try: query_set = session.query(cls).filter_by(**params) _total = query_set.count() if _count: return _total if _limit is None: raise JHTTPBadRequest('Missing _limit') _start, _limit = process_limit(_start, _page, _limit) # Filtering by fields has to be the first thing to do on the query_set! query_set = cls.apply_fields(query_set, _fields) query_set = cls.apply_sort(query_set, _sort) query_set = query_set.offset(_start).limit(_limit) if not query_set.count(): msg = "'%s(%s)' resource not found" % (cls.__name__, params) if __raise_on_empty: raise JHTTPNotFound(msg) else: log.debug(msg) except (InvalidRequestError,) as e: raise JHTTPBadRequest(str(e), extra={'data': e}) query_sql = str(query_set).replace('\n', '') if _explain: return query_sql log.debug('get_collection.query_set: %s (%s)', cls.__name__, query_sql) query_set._nefertari_meta = dict( total=_total, start=_start, fields=_fields) return query_set