반응형
(SQLAlechemy 보다 편리한) SQLModel + FastAPI 이용
파이썬 및 FastAPI에서 데이터베이스 연결 및 모델을 다룰 때, SQLAlchemy를 많이 이용하는데,
그것 대신에 SQLModel을 이용하면 훨씬 간결한 코드로 처리할 수 있습니다.
🔥 GitHub Repository: https://github.com/ArjanCodes/examples/tree/main/2024/sqlmodel
🎓 ArjanCodes Courses: https://www.arjancodes.com/courses.
🔖 Chapters:
0:30 SQLAlchemy Overview and Limitations
5:41 SQLModel Basics
12:23 Advanced Example with Relationships
15:46 Additional SQLModel Features
16:24 When to Use SQLModel and When to Stick with SQLAlchemy
17:18 One caveat with SQLModel 19:06 Outro
https://www.youtube.com/watch?v=GONyd0CUrPc
[ 예제 1 ] SQLAlchemy 이용
from typing import Optional
import uvicorn
from fastapi import Depends, FastAPI, HTTPException
from pydantic import BaseModel
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session, sessionmaker
# SQLAlchemy model
Base = declarative_base()
class DBHero(Base):
__tablename__ = "heroes"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
secret_name = Column(String)
age = Column(Integer, nullable=True)
# Pydantic models
class Hero(BaseModel):
id: Optional[int] = None
name: str
secret_name: str
age: Optional[int] = None
# FastAPI app
app = FastAPI()
# Database setup
DATABASE_URL = "sqlite:///./database.db"
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base.metadata.create_all(bind=engine)
# Dependency
def get_session():
db = SessionLocal()
try:
yield db
finally:
db.close()
# Create a Hero
@app.post("/heroes/", response_model=Hero)
def create_hero(hero: Hero, session: Session = Depends(get_session)):
db_hero = DBHero(**hero.model_dump())
session.add(db_hero)
session.commit()
session.refresh(db_hero)
return db_hero
# Read all heroes
@app.get("/heroes/", response_model=list[Hero])
def read_heroes(
skip: int = 0, limit: int = 10, session: Session = Depends(get_session)
):
heroes = session.query(DBHero).offset(skip).limit(limit).all()
return heroes
# Read a hero by ID
@app.get("/heroes/{hero_id}", response_model=Hero)
def read_hero(hero_id: int, session: Session = Depends(get_session)):
hero = session.query(DBHero).filter(DBHero.id == hero_id).first()
if not hero:
raise HTTPException(status_code=404, detail="Hero not found")
return hero
# Update a Hero
@app.put("/heroes/{hero_id}", response_model=Hero)
def update_hero(hero_id: int, hero_data: Hero, session: Session = Depends(get_session)):
hero = session.query(DBHero).filter(DBHero.id == hero_id).first()
if not hero:
raise HTTPException(status_code=404, detail="Hero not found")
# Update the hero's attributes
for field, value in hero_data.model_dump().items():
setattr(hero, field, value)
session.commit()
session.refresh(hero)
return hero
# Delete a Hero
@app.delete("/heroes/{hero_id}", response_model=Hero)
def delete_hero(hero_id: int, session: Session = Depends(get_session)):
hero = session.query(DBHero).filter(DBHero.id == hero_id).first()
if not hero:
raise HTTPException(status_code=404, detail="Hero not found")
session.delete(hero)
session.commit()
return hero
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8000)
[ 예제 2 ] SQLModel 이용
from typing import Optional
import uvicorn
from fastapi import Depends, FastAPI, HTTPException
from sqlmodel import Field, Session, SQLModel, create_engine, select
# Define the Hero model
class Hero(SQLModel, table=True):
id: Optional[int] = Field(primary_key=True)
name: str
secret_name: str
age: Optional[int]
# Create the FastAPI app
app = FastAPI()
# Create the SQLite database engine
engine = create_engine("sqlite:///database.db")
SQLModel.metadata.create_all(engine)
# Dependency: Get the session
def get_session():
with Session(engine) as session:
yield session
# Create a Hero
@app.post("/heroes", response_model=Hero)
def create_hero(hero: Hero, session: Session = Depends(get_session)):
session.add(hero)
session.commit()
session.refresh(hero)
return hero
# Read all heroes
@app.get("/heroes", response_model=list[Hero])
def read_heroes(
skip: int = 0, limit: int = 10, session: Session = Depends(get_session)
):
heroes = session.exec(select(Hero).offset(skip).limit(limit)).all()
return heroes
# Read a hero by ID
@app.get("/heroes/{hero_id}", response_model=Hero)
def read_hero(hero_id: int, session: Session = Depends(get_session)):
hero = session.get(Hero, hero_id)
if not hero:
raise HTTPException(status_code=404, detail="Hero not found")
return hero
# Update a Hero
@app.put("/heroes/{hero_id}", response_model=Hero)
def update_hero(hero_id: int, hero_data: Hero, session: Session = Depends(get_session)):
hero = session.get(Hero, hero_id)
if not hero:
raise HTTPException(status_code=404, detail="Hero not found")
# Update the hero's attributes
for field, value in hero_data.model_dump().items():
setattr(hero, field, value)
session.commit()
session.refresh(hero)
return hero
# Delete a Hero
@app.delete("/heroes/{hero_id}", response_model=Hero)
def delete_hero(hero_id: int, session: Session = Depends(get_session)):
hero = session.get(Hero, hero_id)
if not hero:
raise HTTPException(status_code=404, detail="Hero not found")
session.delete(hero)
session.commit()
return hero
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=8000)
반응형
'FastAPI' 카테고리의 다른 글
FastAPI 테스트 (with pytest) (0) | 2025.01.05 |
---|---|
FastAPI 실시간 대화방 예제 (0) | 2024.12.21 |
SQLAlchemy, 객체 값 업데이트 setattr () (0) | 2024.12.19 |
FastAPI, Jinja 기본 예제 (2) | 2024.12.18 |
FastAPI, CRUD API 예제 (0) | 2024.12.17 |