코딩캠프/AI 웹개발 취업캠프

[AI 웹개발 취업캠프] 24Day - FastAPI(4)

고랑E 2023. 8. 18. 19:05
728x90

FastAPI

SQLAlchemy

📦app
 ┣ 📜crud.py
 ┣ 📜database.py
 ┣ 📜main.py
 ┣ 📜models.py
 ┣ 📜schemas.py
 ┗ 📜__init__.py

다음 파일 구조에서 데이터베이스와 연결을 해보자

 

database.py

FastAPI 자습서의 데이터베이스 연결부분에 아래의 예시 코드가 있다.

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"
# SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db"

engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

 

SQLAlchemy 라는 ORM 으로 MySQL 데이터베이스를 Pymysql 라이브러리를 이용해서 연결을 할꺼다.

여기서 SQLALCHEMY_DATABASE_URL 를 작성한다.

mysql+pymysql://{ID}:{PASSWORD}@{HOST}:{PORT}/{DATABASE}

맨 앞 mysql+pymysql 는  MySQL 데이터베이스와 pymysql 라이브러리를 사용한다는 뜻이다

 

만약

id: nipa

password: 1234

host: 127.0.0.1

port: 3306

database: nipa_myweb

이면 다음과 같이 입력한다.

mysql+pymysql://nipa:1234@127.0.0.1:3306/nipa_myweb

 

models.py

from sqlalchemy import Column, Integer, String, DateTime, Boolean
from sqlalchemy.sql import func
from .database import Base
from datetime import datetime
import bcrypt

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True, comment='유저 고유 id')
    loginId = Column(String(10), unique=True, index=True, nullable=False, comment='유저 로그인아이디')
    nickname = Column(String(10), unique=True, nullable=False, comment='유저 닉네임')
    password = Column(String(100), nullable=False, comment='유저 비밀번호(암호화)')
    email = Column(String(50), unique=True, nullable=False, comment='유저 이메일')
    emailVerified = Column(Boolean, default=False, comment='이메일 인증 여부')
    introduction = Column(String(255), default='', comment='유저 자기소개')
    image = Column(String(255), default='/./images/baseprofile.png', comment='유저 프로필 사진')
    loginMethod = Column(String(6), default='local', comment='로그인 구분')
    createdAt = Column(DateTime(timezone=True), server_default=func.now(), nullable=False, comment='계정 생성 시간')
    updatedAt = Column(DateTime(timezone=True), onupdate=func.now(), nullable=False, comment='계정 정보 수정 시간')

    def hash_password(self):
        self.password = bcrypt.hashpw(self.password.encode('utf-8'), bcrypt.gensalt())

 

테이블, 그 테이블의 컬럼들, 제약조건 및 데이터타입 등을 적어준다

외래키가 있을경우

from sqlalchemy.orm import relationship

을 추가해주고

https://fastapi.tiangolo.com/tutorial/sql-databases/#create-the-relationships 를 참고해 수정해준다.

 

schemas.py

from typing import List, Union
from pydantic import BaseModel

class User(BaseModel):
    loginId: str
    nickname: str
    password: str
    email: str
    emailVerified: bool
    introduction: str
    image: str
    loginMethod: str

class UserCreate(BaseModel):
    loginId: str
    nickname: str
    password: str
    email: str

데이터베이스 모델과 api 간 데이터 교환을 위해 스키마를 정의 해주고 데이터 유효성 검사를 pydantic 라이브러리를 사용한다.

 

crud.py

from sqlalchemy.orm import Session
from . import models, schemas
import bcrypt
from datetime import datetime

def create_user(db: Session, user: schemas.UserCreate):
    hashed_password = bcrypt.hashpw(user.password.encode('utf-8'), bcrypt.gensalt())
    db_user = models.User(
        loginId=user.loginId,
        nickname=user.nickname,
        password=hashed_password,
        email=user.email,
        createdAt=datetime.now(),
        updatedAt=datetime.now()
    )
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user

에서 처럼 생성, 읽기, 수정, 삭제를 수행한다.

 

main.py

from fastapi import FastAPI, Depends
from fastapi.responses import JSONResponse
from sqlalchemy.orm import Session
from . import crud, models, schemas, database

app = FastAPI()

def get_db():
    db = database.SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.post("/join/", response_model=schemas.User)
def join(user: schemas.UserCreate, db: Session = Depends(get_db)):
    crud.create_user(db, user)
    return JSONResponse(content={"message": "가입이 완료되었습니다."}, status_code=201)

라우터를 통해 각 작업을 수행한다.

 

본 후기는 정보통신산업진흥원(NIPA)에서 주관하는 <AI 서비스완성! AI+웹개발 취업캠프 - 프론트엔드&백엔드> 과정 학습/프로젝트/과제 기록으로 작성되었습니다.