Issue #4: Pagination logic was repeated across multiple routes. Changes: - Add pagination.py with reusable utilities: - calculate_total_pages: computes page count from total/per_page - calculate_offset: computes offset for given page - create_paginated_response: builds PaginatedResponse with metadata - Update routes/audit.py to use pagination utilities - Update routes/booking.py to use pagination utilities - Update routes/invites.py to use pagination utilities The utilities handle the common pagination math while routes still manage their own query logic (filters, joins, ordering).
46 lines
1.2 KiB
Python
46 lines
1.2 KiB
Python
"""Pagination utilities for API responses."""
|
|
|
|
from typing import TypeVar
|
|
|
|
from pydantic import BaseModel
|
|
|
|
from schemas import PaginatedResponse
|
|
|
|
RecordT = TypeVar("RecordT", bound=BaseModel)
|
|
|
|
|
|
def calculate_total_pages(total: int, per_page: int) -> int:
|
|
"""Calculate total number of pages."""
|
|
return (total + per_page - 1) // per_page if total > 0 else 1
|
|
|
|
|
|
def calculate_offset(page: int, per_page: int) -> int:
|
|
"""Calculate the offset for a given page."""
|
|
return (page - 1) * per_page
|
|
|
|
|
|
def create_paginated_response(
|
|
records: list[RecordT],
|
|
total: int,
|
|
page: int,
|
|
per_page: int,
|
|
) -> PaginatedResponse[RecordT]:
|
|
"""
|
|
Create a paginated response with calculated metadata.
|
|
|
|
Args:
|
|
records: List of records for the current page
|
|
total: Total count of all records (before pagination)
|
|
page: Current page number (1-indexed)
|
|
per_page: Number of records per page
|
|
|
|
Returns:
|
|
A PaginatedResponse with all pagination metadata
|
|
"""
|
|
return PaginatedResponse[RecordT](
|
|
records=records,
|
|
total=total,
|
|
page=page,
|
|
per_page=per_page,
|
|
total_pages=calculate_total_pages(total, per_page),
|
|
)
|