FastAPIにてSQLAlchemyを用いたテーブルマイグレーション方法に関する備忘録。
こちらの記事の続きで、Supabase(PostgreSQL)にテーブルの変更内容を反映させることを目的としています。
SQLAlchemy公式のマイグレーションツールであるAlembicを導入する手順を紹介します。
✅ Alembic 導入手順
1. 依存ライブラリを追加
requirements.txt
に追加:
alembic==1.13.1
インストール:
pip install alembic
and add alembic==1.15.2 in requirements.txt
2.初期化
alembic init alembic
alembic
folder and alembic.ini
file will be created.
3.alembic.ini
sqlalchemy.url =
Not to specify database url here.
4.alembic/env.py
初期化で生成されたenv.pyを以下のように変更する。
import os
from logging.config import fileConfig
from dotenv import load_dotenv
from sqlalchemy import pool
from alembic import context
load_dotenv()
DATABASE_URL = os.getenv("SYNC_DATABASE_URL_ALEMBIC")
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config
# Interpret the config file for Python logging.
# This line sets up loggers basically.
if config.config_file_name is not None:
fileConfig(config.config_file_name)
# add your model's MetaData object here
# for 'autogenerate' support
from app.models.base import Base
# target_metadata = mymodel.Base.metadata
target_metadata = Base.metadata
def run_migrations_offline() -> None:
url = config.get_main_option("sqlalchemy.url")
if not url:
url = DATABASE_URL
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def run_migrations_online() -> None:
url = config.get_main_option("sqlalchemy.url")
if not url:
url = DATABASE_URL
from sqlalchemy import create_engine
connectable = create_engine(url, poolclass=pool.NullPool)
with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
)
with context.begin_transaction():
context.run_migrations()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
ポイント
- FastAPI + Alembic の場合、SYNC(同期ドライバ)psycopg2を使う必要がある。
- アプリ側で
+asyncpg
、ASYNC(非同期)として接続。
.env
DATABASE_URL=postgresql+asyncpg://[YOUR_PROJECT].xxxx.supabase.com:5432/postgres # app
SYNC_DATABASE_URL_ALEMBIC=postgresql://[YOUR_PROJECT].xxxx.supabase.com:6543/postgres #Alembic
app/models/__init__.py
from .message import Message
from .user import User
from .conversation import Conversation
app/models/base.py
from sqlalchemy.orm import declarative_base
Base = declarative_base()
このBaseをalembic/env.py 内で使う
Modify Message Model
from sqlalchemy import Column, String, ForeignKey, DateTime, Enum
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
import uuid
from datetime import datetime
class Message(Base):
__tablename__ = "messages"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
conversation_id = Column(UUID(as_uuid=True), ForeignKey("conversations.id"), nullable=False)
role = Column(String, nullable=False) # 'user' or 'assistant'
content = Column(String, nullable=False)
translated_content = Column(String, nullable=True)
audio_url = Column(String, nullable=True) # Add new column
created_at = Column(DateTime, default=datetime.utcnow)
conversation = relationship("Conversation", back_populates="messages")
5.Create migration file
alembic revision --autogenerate -m "add audio_url"
alembic/versions
内にファイルが自動生成される。
生成されたファイルがマイグレーションの変更内容になる。
たまに間違っていることがあるので、中身を適宜確認する。
以下のようなファイルが生成されれば、OK。
alembic/versions/32d973e73589_add_audio_url.py
"""add audio url
Revision ID: 32d973e73589
Revises:
Create Date: 2025-04-12 15:15:43.383714
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = '32d973e73589'
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:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('message', sa.Column('audio_url', sa.String(), nullable=True))
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('message', 'audio_url')
# ### end Alembic commands ###
6.Execute migration
alembic upgrade head
コマンド実行後、テーブル変更内容が反映されていればOK。