Study/fastapi

fastapi + sqlalchemy + ORM을 이용한 페이지네이션 방법들

bluebamus 2025. 1. 14.

1. Offset/Limit 방식

   - skip : 몇 개의 항목을 건너뛸지 결정한다.
   - limit : 가져올 항목의 최대 개수를 설정한다.

from fastapi import FastAPI, Query, Depends, HTTPException
from sqlalchemy.orm import Session
from pydantic import BaseModel
from typing import List, Any
from .database import get_db
from .models import Item

app = FastAPI()

# Response schema for consistent structure
class PaginatedResponse(BaseModel):
    total: int  # Total number of items
    skip: int  # Current skip value
    limit: int  # Current limit value
    data: List[Any]  # List of items

@app.get("/items/", response_model=PaginatedResponse)
def read_items(
    skip: int = Query(0, ge=0, description="Number of items to skip"),
    limit: int = Query(10, ge=1, le=100, description="Number of items to fetch"),
    db: Session = Depends(get_db)
):
    # Count total items for pagination
    total = db.query(Item).count()

    # Retrieve paginated items
    items = db.query(Item).offset(skip).limit(limit).all()

    # Return a structured response
    return {
        "total": total,
        "skip": skip,
        "limit": limit,
        "data": items,
    }

 

2. Cursor 기반 페이지네이션

   - Cursor 기반 페이지네이션은 고유한 ID를 기준으로 다음 페이지의 시작점을 결정한다.

   - cursor : 마지막으로 가져온 항목의 ID를 기준으로 다음 페이지를 가져온다.

from fastapi import FastAPI, Query, Depends
from sqlalchemy.orm import Session
from .database import get_db
from .models import Item

app = FastAPI()

@app.get("/items/")
def read_items(cursor: int = Query(None), limit: int = 10, db: Session = Depends(get_db)):
    query = db.query(Item)
    if cursor:
        query = query.filter(Item.id > cursor)
    items = query.order_by(Item.id).limit(limit).all()
    return items

 

3. SQLAlchemy Paginator 라이브러리 사용

   - SQLAlchemy Paginator와 같은 라이브러리를 사용하여 페이지네이션을 간편하게 처리할 수 있다.

   - page : 가져올 페이지 번호를 설정한다.
   - size : 페이지당 항목 수를 설정한다.

from fastapi import FastAPI, Query, Depends
from sqlalchemy.orm import Session
from sqlalchemy_pagination import paginate
from .database import get_db
from .models import Item

app = FastAPI()

@app.get("/items/")
def read_items(
    page: int = Query(1, description="가져올 페이지 번호 (1부터 시작)"),
    size: int = Query(10, description="페이지당 항목 수"),
    db: Session = Depends(get_db),
):
    """
    항목 목록을 페이지네이션하여 반환합니다.

    Args:
        page (int): 가져올 페이지 번호입니다.
        size (int): 페이지당 항목 수입니다.
        db (Session): 데이터베이스 세션 객체입니다.

    Returns:
        dict: 페이지네이션된 결과를 포함한 객체입니다.
    """
    query = db.query(Item)
    result = paginate(query, page, size)
    return {
        "total": result.total,
        "pages": result.pages,
        "current_page": result.page,
        "items": result.items,
    }

 

댓글