def get_all_translation_opportunities( cls, page_size: int, urlsafe_start_cursor: Optional[str], language_code: str ) -> Tuple[List['ExplorationOpportunitySummaryModel'], Optional[str], bool]: """Returns a list of opportunities available for translation in a specific language. Args: page_size: int. The maximum number of entities to be returned. urlsafe_start_cursor: str or None. If provided, the list of returned entities starts from this datastore cursor. Otherwise, the returned entities start from the beginning of the full list of entities. language_code: str. The language for which translation opportunities are to be fetched. Returns: 3-tuple of (results, cursor, more). As described in fetch_page() at: https://developers.google.com/appengine/docs/python/ndb/queryclass, where: results: list(ExplorationOpportunitySummaryModel). A list of query results. cursor: str or None. A query cursor pointing to the next batch of results. If there are no more results, this might be None. more: bool. If True, there are (probably) more results after this batch. If False, there are no further results after this batch. """ if urlsafe_start_cursor: start_cursor = datastore_services.make_cursor( urlsafe_cursor=urlsafe_start_cursor) else: start_cursor = datastore_services.make_cursor() language_query = cls.query( cls.incomplete_translation_language_codes == language_code).order( cls.incomplete_translation_language_codes) results, cursor, _ = (language_query.fetch_page( page_size, start_cursor=start_cursor)) # TODO(#13462): Refactor this so that we don't do the lookup. # Do a forward lookup so that we can know if there are more values. plus_one_query_models, _, _ = (language_query.fetch_page( page_size + 1, start_cursor=start_cursor)) more_results = len(plus_one_query_models) == page_size + 1 # The urlsafe returns bytes and we need to decode them to string. return (cast(List[ExplorationOpportunitySummaryModel], results), (cursor.urlsafe().decode('utf-8') if cursor else None), more_results)
def fetch_page( cls, page_size: int, urlsafe_start_cursor: Optional[str], sort_by: Optional[str] ) -> Tuple[List['SkillSummaryModel'], Optional[str], bool]: """Returns the models according to values specified. Args: page_size: int. Number of skills to fetch. urlsafe_start_cursor: str|None. The cursor to the next page or None. If None, this means that the search should start from the first page of results. sort_by: str|None. A string indicating how to sort the result. Returns: 3-tuple(query_models, urlsafe_start_cursor, more). where: query_models: list(SkillSummary). The list of summaries of skills starting at the given cursor. urlsafe_start_cursor: str or None. A query cursor pointing to the next batch of results. If there are no more results, this might be None. more: bool. If True, there are (probably) more results after this batch. If False, there are no further results after this batch. """ cursor = ( datastore_services.make_cursor(urlsafe_cursor=urlsafe_start_cursor)) sort = -cls.skill_model_created_on if sort_by == ( constants.TOPIC_SKILL_DASHBOARD_SORT_OPTIONS[ 'DecreasingCreatedOn']): sort = cls.skill_model_created_on elif sort_by == ( constants.TOPIC_SKILL_DASHBOARD_SORT_OPTIONS[ 'IncreasingUpdatedOn']): sort = -cls.skill_model_last_updated elif sort_by == ( constants.TOPIC_SKILL_DASHBOARD_SORT_OPTIONS[ 'DecreasingUpdatedOn']): sort = cls.skill_model_last_updated sort_query = cls.query().order(sort) query_models, next_cursor, _ = ( sort_query.fetch_page(page_size, start_cursor=cursor)) # TODO(#13462): Refactor this so that we don't do the lookup. # Do a forward lookup so that we can know if there are more values. plus_one_query_models, _, _ = ( sort_query.fetch_page(page_size + 1, start_cursor=cursor)) # The urlsafe returns bytes and we need to decode them to string. more_results = len(plus_one_query_models) == page_size + 1 new_urlsafe_start_cursor = ( next_cursor.urlsafe().decode('utf-8') if (next_cursor and more_results) else None ) return ( cast(List[SkillSummaryModel], query_models), new_urlsafe_start_cursor, more_results)
def get_skill_opportunities( cls, page_size: int, urlsafe_start_cursor: Optional[str] ) -> Tuple[Sequence['SkillOpportunityModel'], Optional[str], bool]: """Returns a list of skill opportunities available for adding questions. Args: page_size: int. The maximum number of entities to be returned. urlsafe_start_cursor: str or None. If provided, the list of returned entities starts from this datastore cursor. Otherwise, the returned entities start from the beginning of the full list of entities. Returns: 3-tuple of (results, cursor, more). As described in fetch_page() at: https://developers.google.com/appengine/docs/python/ndb/queryclass, where: results: list(SkillOpportunityModel). A list of query results. cursor: str or None. A query cursor pointing to the next batch of results. If there are no more results, this might be None. more: bool. If True, there are (probably) more results after this batch. If False, there are no further results after this batch. """ start_cursor = datastore_services.make_cursor( urlsafe_cursor=urlsafe_start_cursor) created_on_query = cls.get_all().order(cls.created_on) fetch_result: Tuple[ Sequence[SkillOpportunityModel], datastore_services.Cursor, bool ] = created_on_query.fetch_page(page_size, start_cursor=start_cursor) query_models, cursor, _ = fetch_result # TODO(#13462): Refactor this so that we don't do the lookup. # Do a forward lookup so that we can know if there are more values. fetch_result = created_on_query.fetch_page( page_size + 1, start_cursor=start_cursor) plus_one_query_models, _, _ = fetch_result more_results = len(plus_one_query_models) == page_size + 1 # The urlsafe returns bytes and we need to decode them to string. return ( query_models, (cursor.urlsafe().decode('utf-8') if cursor else None), more_results )
def fetch_exploration_task_history_page( exploration: exp_domain.Exploration, urlsafe_start_cursor: Optional[str] = None ) -> Tuple[List[improvements_domain.TaskEntry], Optional[str], bool]: """Fetches a page from the given exploration's history of resolved tasks. Args: exploration: exp_domain.Exploration. The exploration to fetch the history page for. urlsafe_start_cursor: str or None. Starting point for the search. When None, the starting point is the very beginning of the history results (i.e. starting from the most recently resolved task entry). Returns: tuple. Contains the following 3 items: results: list(improvements_domain.TaskEntry). The query results. urlsafe_cursor: str or None. a query cursor pointing to the "next" batch of results. If there are no more results, this might be None. more: bool. Indicates whether there are (likely) more results after this batch. If False, there are no more results; if True, there are probably more results. """ results: Sequence[improvements_models.TaskEntryModel] = [] start_cursor = (datastore_services.make_cursor( urlsafe_cursor=urlsafe_start_cursor) if urlsafe_start_cursor else None) results, cursor, more = (improvements_models.TaskEntryModel.query( improvements_models.TaskEntryModel.entity_type == ( constants.TASK_ENTITY_TYPE_EXPLORATION), improvements_models.TaskEntryModel.entity_id == exploration.id, improvements_models.TaskEntryModel.status == ( constants.TASK_STATUS_RESOLVED )).order(-improvements_models.TaskEntryModel.resolved_on).fetch_page( feconf.MAX_TASK_MODELS_PER_HISTORY_PAGE, start_cursor=start_cursor)) # The urlsafe returns bytes and we need to decode them to string. return ([get_task_entry_from_model(model) for model in results], cursor.urlsafe().decode('utf-8') if cursor else None, more)