Cursor-Based pagination uses a unique identifier (a cursor) to track the current position in the dataset. This is the most efficient method for large datasets and provides consistent results even if the underlying data changes. However, it is more complex to implement and requires a unique, sequential field to serve as the cursor.
To use it, configure the page type using set_page(CursorPage[T]) and the parameters using set_params(CursorParams(size=N)). When using SQLAlchemy, use the paginate function from fastapi_pagination.ext.sqlalchemy.
from pydantic import BaseModel
from sqlalchemy import create_engine, select
from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column
from fastapi_pagination import set_params, set_page
from fastapi_pagination.cursor import CursorPage, CursorParams
from fastapi_pagination.ext.sqlalchemy import paginate
engine = create_engine("sqlite:///:memory:")
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column()
age: Mapped[int] = mapped_column()
class UserOut(BaseModel):
id: int
name: str
age: int
with engine.begin() as conn:
Base.metadata.drop_all(conn)
Base.metadata.create_all(conn)
with Session(engine) as session:
session.add_all(
[
User(name="John", age=25),
User(name="Jane", age=30),
User(name="Bob", age=20),
],
)
session.commit()
set_page(CursorPage[UserOut])
set_params(CursorParams(size=10))
page = paginate(session, select(User).order_by(User.id))
print(page.model_dump_json(indent=4))