Skip to content

📖 Pagination ​

Nexios provides a flexible and customizable pagination system that makes managing large datasets a breeze. With support for dynamic page sizes, custom query parameters, and seamless API integration, you can create efficient, user-friendly paginated experiences with minimal code.

🧢 Simple Pagination ​

Here's a quick example of how to paginate a list of items using response.paginate():

python
from nexios import NexiosApp
app = NexiosApp()
@app.get("/get-items")
async def get_items(request, response):
    sample_data = [{"id": i, "content": f"Item {i}"} for i in range(1, 101)]
    return response.paginate(sample_data)

you can also use async pagination

python
from nexios import NexiosApp
app = NexiosApp()
@app.get("/get-items")
async def get_items(request, response):
    sample_data = [{"id": i, "content": f"Item {i}"} for i in range(1, 101)]
    return response.apaginate(sample_data)

Output:

py
{
  "items": [
    {
      "id": 1,
      "content": "Item 1"
    },
    {
      "id": 2,
      "content": "Item 2"
    },
    {
      "id": 3,
      "content": "Item 3"
    },
    {
      "id": 4,
      "content": "Item 4"
    },
    {
      "id": 5,
      "content": "Item 5"
    },
    {
      "id": 6,
      "content": "Item 6"
    },
    {
      "id": 7,
      "content": "Item 7"
    },
    {
      "id": 8,
      "content": "Item 8"
    },
    {
      "id": 9,
      "content": "Item 9"
    },
    {
      "id": 10,
      "content": "Item 10"
    },
    {
      "id": 11,
      "content": "Item 11"
    },
    {
      "id": 12,
      "content": "Item 12"
    },
    {
      "id": 13,
      "content": "Item 13"
    },
    {
      "id": 14,
      "content": "Item 14"
    },
    {
      "id": 15,
      "content": "Item 15"
    },
    {
      "id": 16,
      "content": "Item 16"
    },
    {
      "id": 17,
      "content": "Item 17"
    },
    {
      "id": 18,
      "content": "Item 18"
    },
    {
      "id": 19,
      "content": "Item 19"
    },
    {
      "id": 20,
      "content": "Item 20"
    }
  ],
  "pagination": {
    "total_items": 100,
    "total_pages": 5,
    "page": 1,
    "page_size": 20,
    "links": {
      "next": "http://127.0.0.1:8000/3?cursor=eyJpZCI6IDIwfQ%3D%3D&page_size=20?cursor=eyJpZCI6IDIwfQ%3D%3D&page=2&page_size=20",
      "first": "http://127.0.0.1:8000/3?cursor=eyJpZCI6IDIwfQ%3D%3D&page_size=20?cursor=eyJpZCI6IDIwfQ%3D%3D&page=1&page_size=20",
      "last": "http://127.0.0.1:8000/3?cursor=eyJpZCI6IDIwfQ%3D%3D&page_size=20?cursor=eyJpZCI6IDIwfQ%3D%3D&page=5&page_size=20"
    }
  }
}

♟️ Pagination Strategies ​

You can also use other pagination strategies based on your requirements

python
from nexios import NexiosApp
app = NexiosApp()
@app.get("/get-items")
async def get_items(request, response):
    sample_data = [{"id": i, "content": f"Item {i}"} for i in range(1, 101)]
    return response.paginate(sample_data, strategy="cursor")

You can also pass the pagination class directly

py
from nexios import NexiosApp
from nexios.pagination 
app = NexiosApp()
@app.get("/get-items")
async def get_items(request, response):
    sample_data = [{"id": i, "content": f"Item {i}"} for i in range(1, 101)]
    return response.paginate(sample_data, strategy="cursor")

1. Page Number Pagination ​

The most common pagination style, using page numbers and page sizes.

Parameters:

  • page_param: Query parameter name for page number (default: "page")
  • page_size_param: Query parameter name for page size (default: "page_size")
  • default_page: Default page number (default: 1)
  • default_page_size: Default page size (default: 20)
  • max_page_size: Maximum allowed page size (default: 100)

Example URL: /items?page=2&page_size=10

2. Limit-Offset Pagination ​

Traditional SQL-style pagination using limit and offset.

Parameters:

  • limit_param: Query parameter name for limit (default: "limit")
  • offset_param: Query parameter name for offset (default: "offset")
  • default_limit: Default limit value (default: 20)
  • max_limit: Maximum allowed limit value (default: 100)

Example URL: /items?limit=10&offset=20

3. Cursor Pagination ​

Cursor-based pagination for consistent pagination with changing datasets.

Parameters:

  • cursor_param: Query parameter name for cursor (default: "cursor")
  • page_size_param: Query parameter name for page size (default: "page_size")
  • default_page_size: Default page size (default: 20)
  • max_page_size: Maximum allowed page size (default: 100)
  • sort_field: Field to use for cursor sorting (default: "id")

Example URL: /items?cursor=eyJpZCI6IDEwfQ%3D%3D&page_size=10

� Data Handlers ​

Nexios provides both synchronous and asynchronous data handlers: This is an abstract base class that defines the interface for fetching data. You must implement two methods:

Nexios Provide the following data handlers:

SyncDataHandler ​

Base class for synchronous data handlers with two required methods:

  • get_total_items() -> int: Returns total item count
  • get_items(offset: int, limit: int) -> List[Any]: Returns paginated items

Built-in Implementations:

  • SyncListDataHandler: Handles in-memory lists

AsyncDataHandler ​

Base class for asynchronous data handlers with two required methods:

  • async get_total_items() -> int: Returns total item count
  • async get_items(offset: int, limit: int) -> List[Any]: Returns paginated items

Built-in Implementations:

  • AsyncListDataHandler: Handles in-memory lists asynchronously

by default .paginate() uses the AsyncListDataHandler for async functions and SyncListDataHandler for sync functions.

💝 Custom Data Handler ​

You can also create your own data handler by subclassing the SyncDataHandler or AsyncDataHandler classes.

python
from nexios.pagination import AsyncDataHandler
class DatabaseDataHandler(AsyncDataHandler):
    async def get_total_items(self) -> int:
        return await Model.count()
    async def get_items(self, offset: int, limit: int) -> List[Any]:
        return await self.data.offset(offset).limit(limit).all()

@app.get("/get-items")
async def get_items(request, response):
    return response.paginate(data = Items.all(), strategy="cursor", data_handler=DatabaseDataHandler)

In this example , we use DatabaseDataHandler to fetch data from a database using TortoiseORM.

🌟 Custom Pagination Strategy ​

You can also create your own pagination strategy by subclassing the BasePaginationStrategy class.

python
from nexios.pagination import PaginationStrategy
class CustomPaginationStrategy(BasePaginationStrategy):
    def calculate_offset_limit(self, page, page_size):
        return (page - 1) * page_size, page_size

@app.get("/get-items")
async def get_items(request, response):
    return response.paginate(data = [...], strategy=CustomPaginationStrategy)

You can override the following methods:

  • parse_parameters(request_params: Dict[str, Any]) -> Tuple[int, int]
  • generate_metadata(total_items: int, items: List[Any], base_url: str, request_params: Dict[str, Any]) -> Dict[str, Any]
  • calculate_offset_limit(self, page, page_size)

💪 Manual Integration ​

While Nexios provides a convenient way to use pagination, you can also manually integrate pagination into your app.

python
from nexios import NexiosApp
fromnexios.pagination import SyncListDataHandler, PageNumberPagination, SyncPaginator
app = NexiosApp()

@app.get("/get-items")
async def get_items(request, response):

    data_handler = SyncListDataHandler(data=[...])
    pagination_strategy = PageNumberPagination(page_param="page", page_size_param="page_size", default_page=1, default_page_size=20, max_page_size=100)
    paginator = SyncPaginator(data_handler=data_handler, strategy=pagination_strategy)
    return paginator.paginate()

đź’ˇTip

Use this only if you know what you are doing.