Files
prompt/database.py
dsyoon 27540269b7 Initial commit: add FastAPI MVP (모프) and existing web app
Includes FastAPI+Jinja2+HTMX+SQLite implementation with seed categories, plus deployment templates.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-16 17:17:22 +09:00

89 lines
2.4 KiB
Python

"""
database.py
- 기본 DB는 SQLite 파일(`all_prompt.db`)을 사용합니다.
- 나중에 PostgreSQL 등으로 바꾸기 쉽도록 `MOPF_DATABASE_URL` 환경변수를 지원합니다.
- migration 도구 없이 `create_all()`로 테이블을 자동 생성합니다.
요구사항에 등장한 원격 DB 정보(참고):
host: ncue.net
database: all_prompt
user: ncue
password: (문서/코드에 하드코딩하지 말고 환경변수로 전달 권장)
"""
from __future__ import annotations
import os
from typing import Generator
from sqlalchemy import create_engine
from sqlalchemy.orm import Session, sessionmaker
from models import Base, Category
def _default_sqlite_url() -> str:
# 루트에서 `python main.py`를 실행하는 것을 전제로, 현재 작업 디렉토리에 DB 파일이 생성됩니다.
return "sqlite:///./all_prompt.db"
# 이 저장소에는 기존(Next.js/Prisma 등)에서 `DATABASE_URL`을 쓰는 코드가 이미 있을 수 있습니다.
# 따라서 Python MVP는 충돌을 피하려고 별도의 환경변수명을 사용합니다.
DATABASE_URL = os.getenv("MOPF_DATABASE_URL", _default_sqlite_url())
# SQLite는 멀티스레드에서 같은 커넥션을 공유할 때 옵션이 필요합니다.
connect_args = {"check_same_thread": False} if DATABASE_URL.startswith("sqlite") else {}
engine = create_engine(
DATABASE_URL,
connect_args=connect_args,
future=True,
)
SessionLocal = sessionmaker(
bind=engine,
autocommit=False,
autoflush=False,
expire_on_commit=False, # 템플릿 렌더링에서 접근하기 편하게
class_=Session,
)
def get_db() -> Generator[Session, None, None]:
"""FastAPI dependency로 사용하는 DB 세션."""
db = SessionLocal()
try:
yield db
finally:
db.close()
DEFAULT_CATEGORIES = [
# (name, slug)
("글쓰기", "writing"),
("코딩", "coding"),
("업무 자동화", "automation"),
("이미지 생성", "image-generation"),
("데이터 분석", "data-analysis"),
]
def init_db_and_seed() -> None:
"""
- 테이블 생성(create_all)
- 초기 카테고리 seed(이미 있으면 건너뜀)
"""
Base.metadata.create_all(bind=engine)
db = SessionLocal()
try:
existing = db.query(Category).count()
if existing == 0:
for name, slug in DEFAULT_CATEGORIES:
db.add(Category(name=name, slug=slug))
db.commit()
finally:
db.close()