diff --git a/qhana_plugin_registry/api/models/pagination_util.py b/qhana_plugin_registry/api/models/pagination_util.py index 0b47cb6..b521e84 100644 --- a/qhana_plugin_registry/api/models/pagination_util.py +++ b/qhana_plugin_registry/api/models/pagination_util.py @@ -15,9 +15,10 @@ """Module containing helpers for pagination that are better suited for the view functions.""" from dataclasses import dataclass -from typing import Any, Dict, List, Optional, Sequence, Tuple, Type, TypeVar, Union, cast +from typing import Dict, List, Optional, Sequence, Tuple, Type, TypeVar, Union, cast from sqlalchemy.sql.expression import ColumnElement, ColumnOperators +from marshmallow.exceptions import ValidationError from .base_models import ApiLink from .request_helpers import LinkGenerator, PageResource @@ -89,11 +90,13 @@ def prepare_pagination_query_args( item_count: int = 25, sort: Optional[str] = None, _sort_default: str, + _cast_cursor: Optional[type[str] | type[int]] = None, ) -> PaginationOptions: """Prepare pagination query arguments into a PaginationOptions object. Args: _sort_default (str): a default sort string to apply if sort is None + _cast_cursor (type[str]|type[int], optional): if set, ensure that the cursor value is either an int or a string. Defaults to None. cursor (Optional[Union[str, int]], optional): the cursor of the current page. Defaults to None. item_count (int, optional): the current item count. Defaults to 25. sort (Optional[str], optional): the current sort argument. Defaults to None. @@ -104,6 +107,14 @@ def prepare_pagination_query_args( if sort is None and _sort_default is not None: sort = _sort_default + if cursor and _cast_cursor: + try: + cursor = _cast_cursor(cursor) + except ValueError: + raise ValidationError( + f"Page cursor was {cursor} but should have been {'a string' if _cast_cursor is str else 'an integer'}!" + ) + return PaginationOptions( sort=sort, item_count=item_count, diff --git a/qhana_plugin_registry/api/plugins/root.py b/qhana_plugin_registry/api/plugins/root.py index 96b349f..f074dda 100644 --- a/qhana_plugin_registry/api/plugins/root.py +++ b/qhana_plugin_registry/api/plugins/root.py @@ -130,7 +130,7 @@ def get( last_available_period = None pagination_options: PaginationOptions = prepare_pagination_query_args( - **kwargs, _sort_default="name,-version" + **kwargs, _sort_default="name,-version", _cast_cursor=int ) filter_: List[ColumnOperators] = filter_ramps_by_id(parsed_plugin_ids) diff --git a/qhana_plugin_registry/api/seeds/root.py b/qhana_plugin_registry/api/seeds/root.py index 48f6ea3..af6025d 100644 --- a/qhana_plugin_registry/api/seeds/root.py +++ b/qhana_plugin_registry/api/seeds/root.py @@ -64,7 +64,7 @@ def get(self, **kwargs): # abort(HTTPStatus.NOT_IMPLEMENTED, message="WIP, currently not implemented") pagination_options: PaginationOptions = prepare_pagination_query_args( - **kwargs, _sort_default="id" + **kwargs, _sort_default="id", _cast_cursor=int ) pagination_info = default_get_page_info(Seed, tuple(), pagination_options) diff --git a/qhana_plugin_registry/api/services/root.py b/qhana_plugin_registry/api/services/root.py index f631c78..e0cc523 100644 --- a/qhana_plugin_registry/api/services/root.py +++ b/qhana_plugin_registry/api/services/root.py @@ -63,7 +63,7 @@ def get(self, service_id: Optional[str] = None, **kwargs): """Get a list of services.""" pagination_options: PaginationOptions = prepare_pagination_query_args( - **kwargs, _sort_default="service_id" + **kwargs, _sort_default="service_id", _cast_cursor=int ) service_id_filter = service_id diff --git a/qhana_plugin_registry/api/templates copy/root.py b/qhana_plugin_registry/api/templates copy/root.py index 6583397..7cea4d1 100644 --- a/qhana_plugin_registry/api/templates copy/root.py +++ b/qhana_plugin_registry/api/templates copy/root.py @@ -62,7 +62,7 @@ def get(self, **kwargs): """Get a list of templates.""" pagination_options: PaginationOptions = prepare_pagination_query_args( - **kwargs, _sort_default="name" + **kwargs, _sort_default="name", _cast_cursor=int ) pagination_info = default_get_page_info( diff --git a/qhana_plugin_registry/api/templates/root.py b/qhana_plugin_registry/api/templates/root.py index 8d07c2a..d53f49e 100644 --- a/qhana_plugin_registry/api/templates/root.py +++ b/qhana_plugin_registry/api/templates/root.py @@ -66,7 +66,7 @@ def get(self, **kwargs): template_id: Optional[int] = kwargs.pop("template_id", None) pagination_options: PaginationOptions = prepare_pagination_query_args( - **kwargs, _sort_default="name" + **kwargs, _sort_default="name", _cast_cursor=int ) filter_ = filter_templates_by_template_id(template_id=template_id) diff --git a/qhana_plugin_registry/db/pagination.py b/qhana_plugin_registry/db/pagination.py index 2f13869..641a17b 100644 --- a/qhana_plugin_registry/db/pagination.py +++ b/qhana_plugin_registry/db/pagination.py @@ -165,7 +165,7 @@ def get_page_info( DB.session.query( cursor_column, row_numbers.label("row"), - (row_numbers / item_count).label("page"), + func.floor(row_numbers / item_count).label("page"), (row_numbers % item_count).label("modulo"), ) .filter(*query_filter)