import math from typing import Any, Generic, List, TypeVar from django.db.models import QuerySet from ninja import Schema from ninja.pagination import PageNumberPagination T = TypeVar("T") class EnhancedPageNumberPagination(PageNumberPagination): class Output(Schema, Generic[T]): items: List[T] page: int page_size: int total_items: int total_pages: int def paginate_queryset( self, queryset: QuerySet, pagination: PageNumberPagination.Input, **params: Any, ) -> Any: page_size = self._get_page_size(pagination.page_size) offset = (pagination.page - 1) * page_size total_items = self._items_count(queryset) total_pages = math.ceil(total_items / page_size) if page_size > 0 else 0 return { "items": queryset[offset : offset + page_size], "page": pagination.page, "page_size": page_size, "total_items": total_items, "total_pages": total_pages, } async def apaginate_queryset( self, queryset: QuerySet, pagination: PageNumberPagination.Input, **params: Any, ) -> Any: page_size = self._get_page_size(pagination.page_size) offset = (pagination.page - 1) * page_size total_items = await self._aitems_count(queryset) total_pages = math.ceil(total_items / page_size) if page_size > 0 else 0 if isinstance(queryset, QuerySet): items = [obj async for obj in queryset[offset : offset + page_size]] else: items = queryset[offset : offset + page_size] return { "items": items, "page": pagination.page, "page_size": page_size, "total_items": total_items, "total_pages": total_pages, }