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.
**kwargsis 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()
Parameters
Here are the parameters you can use with the cursor pagination:
cursor(int): The primary key of the last object in the previous page.limit(int): The number of items to return in the response.ordering(str): The ordering of the items in the response. It can beascordesc.has_next(bool): Whether there are more items in the next page.
Response fields
items(List): The list of items in the current page.cursor(int): The primary key of the last object in the current page.limit(int): The number of items in the current page.ordering(str): The ordering of the items in the current page.has_next(bool): Whether there are more items in the next page.
Sample Request
You can pass the following query parameters to the endpoint to get the paginated response:
with the cursor param
without the cursor param
Without the cursor param, the first page will be selected by default, and
a list of items will be returned depending on the limit,
and the ordering.
Sample Response
{
"items": [
{
"id": 0,
"title": "string",
"description": "string",
"completed_at": "2024-03-14T03:37:19.015Z",
"will_be_completed_at": "2024-03-14T03:37:19.015Z",
"created_at": "2024-03-14T03:37:19.015Z",
"updated_at": "2024-03-14T03:37:19.015Z"
}
],
"cursor": 0,
"limit": 0,
"ordering": "asc",
"has_next": true
}
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,
}
How to?
How to implement async with pagination?
Pagination is similar! No changes required, i.e.: