Skip to content

Pagination

You want something, djapily paginated? Right place you're in.

We provide three pagination out of the box; OffsetLimitPagination, PageNumberPagination and CursorPagination.

OffsetLimitPagination

This is the default pagination mechanism in Djapy. It's simple and easy to use. It's based on the offset and limit query parameters. Here's how you can use it:

from djapy.pagination import OffsetLimitPagination, paginate


@djapify  # required
@paginate(OffsetLimitPagination)  # required, OR just @paginate, params: offset=0, limit=10
def todo_list(request, **kwargs) -> List[Todo]:
    return Todo.objects.all()

Make sure to add paginate decorator to your view and pass the pagination class as an argument. List[Todo] is the return type hint of the view, also for Swagger documentation.

**kwargs is required to pass the pagination parameters to the view.

PageNumberPagination

This is another pagination mechanism in Djapy. It's based on the page and page_size query parameters. Here's how you can use it:

from djapy.pagination import PageNumberPagination, paginate


@djapify  # required
@paginate(PageNumberPagination)  # required, OR just @paginate, params: page_number=1, page_size=10
def todo_list(request, **kwargs) -> List[Todo]:
    return Todo.objects.all()

CursorPagination

This is the last pagination mechanism in Djapy. It's based on the cursor query parameter. Here's how you can use it:

from djapy.pagination import CursorPagination, paginate


@djapify  # required
@paginate(CursorPagination)  # required, OR just @paginate, params: cursor=0, limit=10
def todo_list(request, **kwargs) -> List[Todo]:
    return Todo.objects.all()

cursor is the primary key of the last object in the previous page.

Extending Base Pagination

You can extend the base pagination mechanism to create your own custom pagination mechanism.

Here's an example of how you can do that:

from djapy.pagination import BasePagination
from pydantic import model_validator


class CursorPagination(BasePagination):  # example
    """Cursor-based pagination."""

    query = [
        ('cursor', conint(ge=0), 0),
        ('limit', conint(ge=0), 1),
        # ... your custom query parameters here
    ]

    class response(Schema, Generic[G_TYPE]):
        items: G_TYPE
        cursor: int | None
        limit: int
        has_next: bool

        # ... your custom fields here

        @model_validator(mode="before")
        def make_data(cls, queryset, info):
            if not isinstance(queryset, QuerySet):
                raise ValueError("The result should be a QuerySet")
            # ... your custom logic here

            return {
                "items": queryset_subset,
                "cursor": cursor,
                "limit": limit,
                "has_next": has_next,
            }