def borrows(self, data_list): successful_borrows = [] user = User.get_by_id(data_list[0]["user"]["user_id"]) with database.atomic(): num_book_borrowing = BookCirculation.select().where( (BookCirculation.user == user) & (BookCirculation.return_time.is_null(True))).count() if num_book_borrowing + len(data_list) > 5: raise BorrowingExceededError() for data in data_list: book = Book.get_by_id(data["book"]["book_id"]) data['book'] = book data['user'] = user if BookCirculation.select().where( (BookCirculation.book == book) & (BookCirculation.return_time.is_null(True))).count() != 0: raise AlreadyBorrowedError() successful_borrows.append(BookCirculation.create(**data)) SendBorrowNotification(successful_borrows).start() return successful_borrows
def search_content(self, params): index = search.Index(config.content_index) search_text = '' # This search_results objects has properties `number_found`, `results`, # and `cursor`. See # https://cloud.google.com/appengine/docs/python/search/searchresultsclass # search.Query docs: # https://cloud.google.com/appengine/docs/python/search/queryclass # search.QueryOptions docs: # https://cloud.google.com/appengine/docs/python/search/queryoptionsclass # Pagination using a 'page' argument pulls n arguments offset by n*page # pull first set of results with page=0 page_size = 20 offset = 0 if 'page' in params: offset = int(params.pop('page')) * page_size # Build the SortOptions with 2 sort keys sort1 = search.SortExpression( expression='display_order', direction=search.SortExpression.DESCENDING, default_value=0) sort2 = search.SortExpression( expression='votes_for', direction=search.SortExpression.DESCENDING, default_value=0) sort3 = search.SortExpression( expression='created', direction=search.SortExpression.DESCENDING, default_value=0) sort_opts = search.SortOptions(expressions=[sort1, sort2, sort3]) search_results = index.search( search.Query(query_string=self._stringify_search_params(params), options=search.QueryOptions( limit=page_size, offset=offset, snippeted_fields=['summary', 'body'], sort_options=sort_opts, ))) for result in search_results.results: if 'Chapter_' in result.doc_id: book_id = None for field in result.fields: if field.name == 'books': book_id = field.value if book_id: book = Book.get_by_id(book_id) result.fields.append(search.TextField('bookUID', book.uid)) result.fields.append( search.TextField('bookTitle', book.title)) result.fields.append( search.TextField( 'bookIcon', util.extract_value_from_json(book.icon, 'link'))) result.fields.append( search.TextField( 'chapterNumber', str(book.chapters.index(result.doc_id) + 1))) result_dicts = [ util.search_document_to_dict(doc) for doc in search_results.results ] result_dicts = self._annotate_search_content(result_dicts) return result_dicts
def delete(self, id): if not self.user: raise PermissionDenied("Public cannot delete.") logging.info(u'Api.delete(id={})'.format(id)) entity = Model.get_by_id(id) if self.user.is_admin: allowed = True elif isinstance(entity, (Book, Page)): allowed = self.user.uid in entity.authors elif isinstance(entity, Chapter): books = Book.get_by_id(entity.books) or [] allowed = all(self.user.uid in b.authors for b in books) else: allowed = entity.key.parent() == self.user.key if not allowed: raise PermissionDenied( "{} does not own {} and may not delete it.".format( self.user, entity)) entity.deleted = True # We're about to take it out of the index, so don't bother updating # it with the new value of the deleted property. # See model.Model._post_put_hook() entity.forbid_post_put_hook = True entity.put() if isinstance(entity, (Book, Page)): logging.info("Removing soft-deleted content from search.") search.Index(config.content_index).delete(entity.uid) entity_kind = Model.get_kind(entity) # If User object, need to remove unique properties from unique model if entity_kind is 'User': entity.remove_unique_properties(entity) # If vote, need to decrement vote on subject object if entity_kind is 'Vote': if entity.page_id: page_id = entity.page_id page = Page.get_by_id(page_id) if page is not None: page.votes_for = max(page.votes_for - 1, 0) page.put() if entity.book_id: book_id = entity.book_id book = Book.get_by_id(book_id) if book is not None: book.votes_for = max(book.votes_for - 1, 0) book.put() if entity_kind is 'Comment': if entity.page_id: page_id = entity.page_id page = Page.get_by_id(page_id) if page is not None: page.num_comments = max(page.num_comments - 1, 0) page.put() if entity.book_id: book_id = entity.book_id book = Book.get_by_id(book_id) if book is not None: book.num_comments = max(book.num_comments - 1, 0) book.put()