On this page
article
FastAPI Database Integration
Integrate SQLAlchemy with FastAPI — async database sessions, CRUD operations, and dependency injection.
FastAPI works seamlessly with SQLAlchemy for database operations. This guide covers the modern async approach.
Setup
pip install sqlalchemy asyncpg # PostgreSQL async driver
# or: pip install aiosqlite # SQLite async driver
Database Configuration
# app/database.py
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
from sqlalchemy.orm import DeclarativeBase
DATABASE_URL = "sqlite+aiosqlite:///./app.db"
engine = create_async_engine(DATABASE_URL, echo=True)
async_session = async_sessionmaker(engine, expire_on_commit=False)
class Base(DeclarativeBase):
pass
async def get_db():
async with async_session() as session:
yield session
Models
# app/models.py
from sqlalchemy import String, Text, DateTime, func
from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base
class Item(Base):
__tablename__ = "items"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(100))
description: Mapped[str] = mapped_column(Text, default="")
created_at: Mapped[DateTime] = mapped_column(DateTime, server_default=func.now())
Pydantic Schemas
# app/schemas.py
from pydantic import BaseModel, ConfigDict
from datetime import datetime
class ItemCreate(BaseModel):
name: str
description: str = ""
class ItemResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
name: str
description: str
created_at: datetime
CRUD Endpoints
# app/routers/items.py
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.database import get_db
from app.models import Item
from app.schemas import ItemCreate, ItemResponse
router = APIRouter(prefix="/items", tags=["items"])
@router.post("/", response_model=ItemResponse, status_code=201)
async def create_item(item: ItemCreate, db: AsyncSession = Depends(get_db)):
db_item = Item(name=item.name, description=item.description)
db.add(db_item)
await db.commit()
await db.refresh(db_item)
return db_item
@router.get("/", response_model=list[ItemResponse])
async def list_items(skip: int = 0, limit: int = 10, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(Item).offset(skip).limit(limit))
return result.scalars().all()
@router.get("/{item_id}", response_model=ItemResponse)
async def get_item(item_id: int, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(Item).where(Item.id == item_id))
item = result.scalar_one_or_none()
if not item:
raise HTTPException(status_code=404, detail="Item not found")
return item
@router.delete("/{item_id}", status_code=204)
async def delete_item(item_id: int, db: AsyncSession = Depends(get_db)):
result = await db.execute(select(Item).where(Item.id == item_id))
item = result.scalar_one_or_none()
if not item:
raise HTTPException(status_code=404, detail="Item not found")
await db.delete(item)
await db.commit()
Initialize Database
# app/main.py
from contextlib import asynccontextmanager
from fastapi import FastAPI
from app.database import engine, Base
@asynccontextmanager
async def lifespan(app: FastAPI):
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield
app = FastAPI(lifespan=lifespan)
FastAPI’s dependency injection system (Depends) makes database session management clean and testable.