1. Introduction
지금까지 데이터 구조를 변경할 시에, 계속 "Drop Table" 쿼리문을 이용하여 변경을 반영시켜주었습니다. 그러나, 이렇게 지속적으로 데이터를 손실을 감행하면서, 데이터 구조의 변형을 반영하는 방법은 현실과 동떨어진 보였고, version contorl을 통해서, 즉각적으로 변경할 수 있는 방법이 있지 않을까라고 생각했습니다.Python sqlalchmey와 연동된 alebmic이란 라이브리를 통해 이를 실현할 수 있었고, 이를 상세하게 적어보겠습니다.
2 Basic Settings
2.1 Initailize steps
터미널에서 아래와 같이, alembic을 설치합니다.
pip install alembic
alembic init -t async 'name'
❗warning
'name'부분은 알맞은 이름을 명시할 것. 예를들어, alembic init migration와 같이 적당한 이름지워넣을 것.
위 명령어를 terminal에 입력한 하면, 자신이 정한 이름과 동일한 폴더가 생성되는 것을 알 수 있습니다
|-migration (* alembic 초기설정에 사용된 이름과 동일한 폴더가 생성됨)
|-versions
|-env.py
|-script.py.mako
|-src
|-db
|-models.py
|-config.py
|-.env
migration/env.py를 들어가서, 아래의 내용을 집어넣어 줍니다.
//env.py
import asyncio
from logging.config import fileConfig
from sqlalchemy import pool
from sqlalchemy.engine import Connection
from sqlalchemy.ext.asyncio import async_engine_from_config
from src.config import settings //아래 내용 참조
from sqlmodel import SQLModel
from alembic import context
SQLALCHEMY_DATABASE_URL=f"postgresql+asyncpg://{settings.postgre_user}:{settings.postgre_password}@{settings.postgre_host}/{settings.postgre_db}"
context.config.set_main_option('sqlalchemy.url',SQLALCHEMY_DATABASE_URL)
target_metadata = SQLModel.metadata
위 내용들을 추가 및 수정해주면, 우리가 할 수 있는 초기화는 다 끝났습니다. 참고로, postgresql 및 기본적인 데이터베이스 host 주소, 패스워드 등의 정보를 .env파일에 집어넣을 수 있습니다. 이를 불러 들여올 때, pydantic 모듈은 각 정보를 class속의 변수(class variables)로 간편하게 사용할 수 있게 해줍니다. 그리고, 정보가 필요한 어는 곳에서 class를 객체화해서 원하는 정보를 불러와서 사용할 수 있습니다. config.py에 pydantic class를 예제로 정해놓았으니, 참고 바랍니다.
//config.py
from dotenv import load_dotenv
from pydantic_settings import BaseSettings
load_dotenv()
class Settings(BaseSettings):
postgre_host:str
postgre_user:str
postgre_password:str
postgre_db:str
secret_key:str
algorithm:str
access_token_expire_days:int
redis_host:str
redis_port:int
class Config:
env_file="./.env"
settings=Settings()
마지막으로, script.py.mako에 들어가서, import sqlmodel을 추가해줍니다.
import sqlmodel //하나 추가할 것
이렇게 해서, 모든 alembic intializing setting은 끝나게 됩니다.
2.2 Implementation
- alembic revision : 뭔가 데이터베이스에 변화를 주고 싶을 때, 쓰는 명령어.
- alembic upgrade: upgrade function에 있는, 명령어를 실행.
- alembic downgrade: downgrade function에 있는 명령어를 실행
*step 1)_ 초기화 메시지를 시켜서, 데이터구조 변경을 실행한다. 아래의 명령어를 실행하면, version folder에 python파일이 생성되게 됩니다.
alembic revision -m 'crate posts table'
윗 생성된 파일을 보면, revision numbe가 생성이 되었는데, 이는 사용자마다 다를 수 있습니다.
*step 2)우리가 원하는 upgrade 내용과 downgade 내용들을 각각 집어넣고 저장한 후, 아래의 commnad 를 입력하면 수정된 내용들이 반영되게 됩니다.
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import sqlmodel
# revision identifiers, used by Alembic.
revision: str = 'fceb720888fc'
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
op.create_table("posts",sa.Column("id",sa.Integer(),nullable=False,primary_key=True),sa.Column("title",sa.String(),nullable=False))
pass
def downgrade() -> None:
op.drop_table("posts")
pass
원하는 코드를 사용한 후에, upgrade를 원할 경우 revision 문자열과 함께 아래의 코드를 실행합니다. 만약, 다시 downgrade를 하고 싶다면 'alembic downgrade -1'을 사용합니다.
//upgrade 사용하고 싶을 경우 (alembic upgrade head)
alembic upgrade fceb720888fc
//downgrande 사요아고 싶을 경우 (alembic downgrade -1)
alembic downgrade fceb720888fc
//현재 내가 사용하고 있는 version을 알고 싶을 때,
alembic current
*step 3) step2의 추가적인 연습
(1) <예제> column을 추가하고 싶을 경우
바로 전 단계에서, 우리 예제로 'posts' 테이블을 생성하였습니다.이제, column 하나를 추가하고 싶을 때, 아래와 같은 field를 집어넣어 줍니다.
alembic revision -m "add colum to post table"
그리고 앞에서 보았듯이, 새로운 파이썬 파일이 생성될 것이고, 각 함수에 column을 추가 해주세요.
def upgrade() -> None:
op.add_column("posts",sa.Column('content',sa.String(),nullable=False))
pass
def downgrade() -> None:
op.drop_column("posts","content")
pass
bash terminal에서 아래와 같은 code를 실행시켜줍니다.
//upgrade 사용하고 싶을 경우
alembic upgrade head
//downgrande 사요아고 싶을 경우 (alembic downgrade -1)
alembic downgrade -1
//현재 내가 사용하고 있는 version을 알고 싶을 때,
alembic current
(2) <예제> foregin-key를 만들어보기
✍️Note
- 이이 user table이 만들어져 있다고 가정합니다.
- user_table의 primary key는 'uid'이며, posts table에 새롭게 추가할 ownder_id와 연관을 짓게 되는 field입니다.
- 두 관계는 1-N이며, 이를 정의내릴 때, on_delete="CASCADE"로 하겠습니다.
alembic revision -m "add foregin-key to posts table"
def upgrade() -> None:
op.add_column("posts",sa.Column("owner_id",sa.UUID(),nullable=False))
op.create_foreign_key("post_users_fk",source_table="posts",referent_table="users",local_cols=['owner_id'],remote_cols=['uid'],ondelete='CASCADE')
pass
def downgrade() -> None:
op.drop_constraint("post_users_fk",table_name="posts")
op.drop_column("posts","owner_id")
pass
위 코드를 저장하고,bash terminal에서 아래의 명령을 수행하면 됩니다.
//upgrade 사용하고 싶을 경우
alembic upgrade head
//downgrande 사요아고 싶을 경우 (alembic downgrade -1)
alembic downgrade -1
//현재 내가 사용하고 있는 version을 알고 싶을 때,
alembic current
'Back-End > Fastapi' 카테고리의 다른 글
10. User 계좌 신규 등록 및 오류 설정 (1) | 2024.11.10 |
---|---|
11. 이메일 인증을 통안 회원가입 및 관리(Email Verification) (0) | 2024.11.10 |
9. Middleware (CORS and Custom Logging) (3) | 2024.10.27 |
8.Error Handling (0) | 2024.10.26 |
6. 역할에 따른 통제권한 (Role-Based Access Control)/Part01 (0) | 2024.10.16 |