FastAPI 테이블 생성 명령(create_all)이 미작동하는 에러

Garam·2024년 9월 16일
post-thumbnail

문제상황

main.py 에 호출한 Base.metadata.create_all(bind=engine) 가 작동하지 않는 상황

# main.py

if __name__ == "__main__":
    uvicorn.run(app, host="localhost", port=8000)
    Base.metadata.create_all(bind=engine)

추론

1. Base 클래스 잘못 사용?

  • core/db.py에서 정의한 Base를 import해서 올바르게 상속받고 있으므로 해당사항 없음
# core/db.py

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from core.config import settings

engine = create_engine(str(settings.SQLALCHEMY_DATABASE_URI), echo=True) # echo -> prints SQL
Session = sessionmaker(bind=engine)
Base = declarative_base()
# models.py

from core.db import Base
from sqlalchemy import Column, Integer, String, Enum, ForeignKey, Date
from sqlalchemy.orm import relationship
from enums import Role

class Department(Base):
    __tablename__ = 'department'

    department_id = Column(Integer, primary_key=True)
    name = Column(String(255), nullable=False)
    members = relationship("Member", back_populates="department")

2. 환경변수?

  • main.py에서 core/config.py에서 정의된, .env 에서부터 import된 변수들을 출력해보니 문제없이 출력되었다.

원인 & 해결방법

테이블 클래스가 Base에 등록되지 않았음

테이블 클래스가 선언된 파일에서 Base.metadata.create_all()을 호출하지 않고, 다른 파일에서 호출되었기 때문에 해당 클래스가 참조되지 않았다. 테이블 클래스가 Base.metadata에 추가되지 않으므로 테이블이 생성되지 않는다.

  • 모든 테이블 클래스가 정의된 파일을 반드시 import 해야한다.
from models import MyTable  # 반드시 import 해야 함

추가 궁금증

  • 만약 이미 테이블이 생성된 상태에서 Base.metadata.create_all()가 실행된다면 어떤 일이 벌어질까?
    • SQLAlchemy는 테이블이 이미 존재한다고 판단해 아무 작업도 수행하지 않고, 따라서 아무 변화가 일어나지 않는다
    • 기존 테이블은 유지된다. 데이터가 삭제되거나 테이블이 새로 생성되지는 않는다.
  • 테이블을 초기화 하고 싶다면 다음 과정을 따라야 한다.
Base.metadata.drop_all()
Base.metadata.create_all()
  • ddl-auto=create과는 다르게 작동함

0개의 댓글