""" Pagination utilities for consistent pagination across the application. """ from typing import Any, Dict, List, Optional from flask import request from sqlalchemy.orm import Query from app.constants import DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE def paginate_query( query: Query, page: Optional[int] = None, per_page: Optional[int] = None, max_per_page: int = MAX_PAGE_SIZE ) -> Dict[str, Any]: """ Paginate a SQLAlchemy query. Args: query: SQLAlchemy query object page: Page number (defaults to request arg or 1) per_page: Items per page (defaults to request arg or DEFAULT_PAGE_SIZE) max_per_page: Maximum items per page Returns: dict with 'items' and 'pagination' keys """ # Get pagination parameters page = page or int(request.args.get("page", 1)) if request else 1 per_page = per_page or int(request.args.get("per_page", DEFAULT_PAGE_SIZE)) if request else DEFAULT_PAGE_SIZE # Enforce maximum per_page = min(per_page, max_per_page) # Paginate paginated = query.paginate(page=page, per_page=per_page, error_out=False) return { "items": paginated.items, "pagination": { "page": paginated.page, "per_page": paginated.per_page, "total": paginated.total, "pages": paginated.pages, "has_next": paginated.has_next, "has_prev": paginated.has_prev, "next_page": paginated.page + 1 if paginated.has_next else None, "prev_page": paginated.page - 1 if paginated.has_prev else None, }, } def get_pagination_params( default_page: int = 1, default_per_page: int = DEFAULT_PAGE_SIZE, max_per_page: int = MAX_PAGE_SIZE ) -> tuple[int, int]: """ Get pagination parameters from request. Returns: tuple of (page, per_page) """ page = int(request.args.get("page", default_page)) if request else default_page per_page = int(request.args.get("per_page", default_per_page)) if request else default_per_page per_page = min(per_page, max_per_page) return page, per_page def create_pagination_links(page: int, per_page: int, total: int, base_url: str) -> Dict[str, Optional[str]]: """ Create pagination links. Args: page: Current page per_page: Items per page total: Total items base_url: Base URL for links Returns: dict with pagination links """ pages = (total + per_page - 1) // per_page if total > 0 else 0 links = { "first": f"{base_url}?page=1&per_page={per_page}" if page > 1 else None, "last": f"{base_url}?page={pages}&per_page={per_page}" if pages > 0 and page < pages else None, "prev": f"{base_url}?page={page-1}&per_page={per_page}" if page > 1 else None, "next": f"{base_url}?page={page+1}&per_page={per_page}" if page < pages else None, } return links