01. PostgreSQL 및 필요 패키지 설치
맥에서 homebrew를 이용하여 PostgreSQL을 다운로드 받은 후 기동
# 맥에서 PostgreSQL 기동 명령어
brew services start postgresql
FastAPI에서는 아래 패키지 설치
#파이썬에서 데이터베이스를 다룰 수 있게 하는 라이브러리
pip install sqlalchemy
#DB 연결 드라이버
pip install psycopg2-binary
**디버깅
참고로 맥북에서 위 명령어대로 패키지를 설치하고 앱을 기동하니 symbol not found in flat namespace '_PQbackendPID' 에러가 발생했었는데 psycopg2-binary를 2.9.9 버전으로 재설치하자 해결되었다.
#기존에 설치 패키지 삭제
pip uninstall -y psycopg2 psycopg2-binary
# 2.9.9 버전으로 설치
pip install --no-cache-dir psycopg2-binary==2.9.9
02. 코드
1) 데이터베이스 연결 : database.py
import os
from dotenv import load_dotenv
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
# .env 파일 읽기
load_dotenv()
DATABASE_URL=os.getenv("DATABASE_URL")
# DB 연결 엔진 생성
# 쿼리 로그를 보려면 echo=True 옵션을 넣을 것
engine = create_engine(DATABASE_URL, echo=False)
# DB 세션 생성기
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
* .env 파일
DATABASE_URL="dialect+driver://username:password@host:port/database"
2) DB 세션 인스턴스 생성(의존성 주입용) : deps.py
from app.db.database import SessionLocal
def get_db():
# 세션 인스턴스 만들기
db = SessionLocal()
try:
yield db
finally:
db.close()
3) DB 조회 호출 : todos.py
from fastapi import APIRouter, Depends
from app.api.deps import get_db
from typing import Annotated
from sqlalchemy.orm import Session
from app.models.todo import Todos
from app.schema.todo import TodoOut
router = APIRouter(tags=["todos"])
# Todos 테이블에 있는 모든 값 조회(결과는 JSON 형식으로-schema에서 정의함)
@router.get("/gettodos", response_model=list[TodoOut])
# DB 세션 만드는 의존성 주입
def read_all(db: Annotated[Session, Depends(get_db)]):
return db.query(Todos).all()
* 데이터베이스 매핑 모델 : models/todos.py
from app.db.database import Base
from sqlalchemy import Column, Integer, String, Boolean
# 파이썬 클래스의 Todos를 DB todos 테이블과 매핑
class Todos(Base):
# 이 클래스가 매핑 될 실제 DB의 테이블명
__tablename__ = 'todos'
id = Column(Integer, primary_key=True, index=True)
title = Column(String)
description = Column(String)
priority = Column(Integer)
complete = Column(Boolean, default=False)