Esempio n. 1
0
def pagination(filtered_instances, path, type_, API_NAME,
               search_params, paginate, page_size):
    """Add pagination to the response and return the response
    :param filtered_instances: instances after filtered from the database query
    :param path: endpoint
    :param type_: type of object to be updated
    :param API_NAME: api name specified while starting server
    :param search_params: Query parameters
    :param paginate: Enable/disable pagination
    :param page_size: Number maximum elements showed in a page
    :return: response containing a page of the objects of that particular type_
    """
    collection_template = {
        "@id": f"{get_host_domain()}/{API_NAME}/{path}/",
        "@context": None,
        "@type": f"{path}",
        "members": []
    }  # type: Dict[str, Any]
    result_length = len(filtered_instances)
    try:
        # To paginate, calculate offset and page_limit values for pagination of search results
        page, page_size, offset = pre_process_pagination_parameters(search_params=search_params,
                                                                    paginate=paginate,
                                                                    page_size=page_size,
                                                                    result_length=result_length)
    except (IncompatibleParameters, PageNotFound, OffsetOutOfRange):
        raise
    current_page_size = page_size
    if result_length - offset < page_size:
        current_page_size = result_length - offset
    for i in range(offset, offset+current_page_size):
        object_template = {
            "@id": f"{get_host_domain()}/{API_NAME}/{type_}/{filtered_instances[i].id}",
            "@type": type_
        }
        collection_template["members"].append(object_template)

    # If pagination is disabled then stop and return the collection template
    collection_template["hydra:totalItems"] = result_length
    if paginate is False:
        return collection_template
    # Calculate last page number
    if result_length != 0 and result_length % page_size == 0:
        last = result_length // page_size
    else:
        last = result_length // page_size + 1
    if page < 1 or page > last:
        raise PageNotFound(str(page))
    recreated_iri = recreate_iri(API_NAME, path, search_params=search_params)
    # Decide which parameter to use to provide navigation
    if "offset" in search_params:
        paginate_param = "offset"
    elif "pageIndex" in search_params:
        paginate_param = "pageIndex"
    else:
        paginate_param = "page"
    attach_hydra_view(collection_template=collection_template, paginate_param=paginate_param,
                      result_length=result_length, iri=recreated_iri, page_size=page_size,
                      offset=offset, page=page, last=last)
    return collection_template
Esempio n. 2
0
def pre_process_pagination_parameters(
        search_params: Dict[str, Any], paginate: bool, page_size: int,
        result_length: int) -> Tuple[int, int, int]:
    """Pre-process pagination related query parameters passed by client.
    :param search_params: Dict of all search parameters.
    :param paginate: Indicates if pagination is enabled/disabled.
    :param page_size: Maximum element a page can contain.
    :param result_length: Length of the list of containing desired items.
    :return: returns page number, page limit and offset.
    """
    incompatible_parameters = ["page", "pageIndex", "offset"]
    incompatible_parameters_len = len(incompatible_parameters)
    # Find any pair of incompatible parameters
    for i in range(incompatible_parameters_len):
        if incompatible_parameters[i] not in search_params:
            continue
        if i != incompatible_parameters_len - 1:
            for j in range(i + 1, incompatible_parameters_len):
                if incompatible_parameters[j] in search_params:
                    raise IncompatibleParameters([
                        incompatible_parameters[i], incompatible_parameters[j]
                    ])
    try:
        # Extract page number from query arguments
        if "pageIndex" in search_params:
            page = int(search_params.get("pageIndex"))
            offset = None
        elif "offset" in search_params:
            offset = int(search_params.get("offset"))
            page = offset // page_size + 1
            if offset > result_length:
                raise OffsetOutOfRange(str(offset))
        else:
            page = int(search_params.get("page", 1))
            offset = None
        if "limit" in search_params:
            limit = int(search_params.get("limit"))
        else:
            limit = None
    except ValueError:
        raise PageNotFound(page)
    page_limit, offset = calculate_page_limit_and_offset(
        paginate=paginate,
        page_size=page_size,
        page=page,
        result_length=result_length,
        offset=offset,
        limit=limit)
    return page, page_limit, offset