Build a generic PaginatedResponse model with total, page, pages, has_next for any list endpoint.
Pagination Pattern
class PaginatedResponse(BaseModel, Generic[T]):
data: list[T]
total: int
page: int
per_page: int
pages: int
def paginate(query, page: int, per_page: int):
total = query.count()
items = query.offset((page-1)*per_page).limit(per_page).all()
return PaginatedResponse(data=items, total=total, page=page,
per_page=per_page, pages=-(-total//per_page))
@app.get("/users", response_model=PaginatedResponse[UserResponse])
def list_users(page: int = Query(1, ge=1), per_page: int = Query(10, ge=1, le=100), db = Depends(get_db)):
return paginate(db.query(User), page, per_page)