目次
3日目 - DBとModelの作成
DBの用意
APIの大枠は作成できたので、中身をこれから作っていく。
まずはdocker-compose.ymlにmysqlコンテナの設定を入れていく
~
db:
image: mysql@5.7
environment:
- MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD
- MYSQL_DATABASE=qiita_copy
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
ports:
- 33306:3306
で、ローカルの環境変数にMYSQL_ROOT_PASSWORDを設定(zsh使いなので.zshrcに記述)
export MYSQL_ROOT_PASSWORD="ルートのパスワード"
mysqlはデフォルトでは日本語入力に対応していないので./mysqlフォルダを作って、その下にmy.cnfを作成
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_bin
[mysql]
default-character-set = utf8mb4
[client]
default-character-set = utf8mb4
でコンテナを立ち上げる
docker-compose up
立ち上がったら中に入って
docker-compose exec db bash
設定したルート用のパスワードでログインできればOK
mysql -uroot -h db -p qiita_copy
DB接続設定
一旦ローカルからbackendの中に入る
docker-compose exec backend bash
sqlalchemyとMySQLドライバーのPyMySQLをインストールする
poetry add sqlalchemy pymysql
インストールし終わったらローカルに戻ってDB接続用のファイルを作成
import os
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
USER_NAME = 'root'
USER = 'root'
PASSWORD = os.environ["MYSQL_ROOT_PASSWORD"]
HOST = 'db'
PORT = 3306
DATABASE = 'qiita_copy'
SQLALCHEMY_DATABASE_URL = "mysql+pymysql://{0}:{1}@{2}:{3}/{4}?charset=utf8".format(
USER,PASSWORD,HOST,PORT,DATABASE
)
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
これでget_dbのメソッドを利用してDBに接続できるようになる。
Modelの作成
DBに接続できるようになったので早速Modelを作っていく
今回はUser、PostとLgtmModelを作る
UserModel
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import relationship
from api.v1.db import Base
import api.v1.models.post # リレーション貼る時に呼び出し順によってはentityが見つけられず、うまく動かなくなるので
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
login_id = Column(String(255), unique=True, nullable=False)
password_hash = Column(String(255), nullable=False)
name = Column(String(255), nullable=False)
description = Column(String(255))
posts = relationship('api.v1.models.post.Post',back_populates='user')
PostModel
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.orm import relationship
from api.v1.db import Base
import api.v1.models.user # リレーション貼る時に呼び出し順によってはentityが見つけられず、うまく動かなくなるので
import api.v1.models.lgtm # リレーション貼る時に呼び出し順によってはentityが見つけられず、うまく動かなくなるので
class Post(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True)
title = Column(String(255), nullable=False)
context = Column(LONGTEXT)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)#ForeignKeyのついたカラムのオプションはForeginKeyより後ろに書かなければならない
user = relationship('api.v1.models.user.User',back_populates="posts") #schemaの設定と同じ命名にしておく
lgtms = relationship('api.v1.models.lgtm.Lgtm',back_populates='post')
LgtmModel
from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.orm import relationship
from api.v1.db import Base
import api.v1.models.post # リレーション貼る時に呼び出し順によってはentityが見つけられず、うまく動かなくなるので
class Lgtm(Base):
__tablename__ = "lgtms"
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
post_id = Column(Integer, ForeignKey("posts.id"), nullable=False)
post = relationship('api.v1.models.post.Post',back_populates='lgtms')
テーブルのマイグレーション
Modelを作成したので、このモデルを元にマイグレーションを作成する。
マイグレーションの管理にはalembicを使うので、いつも通り中に入ってインストールする
docker-compose exec backend bash
poetry add alembic
インストールが完了したら、イニシャライズする。
poetry run alembic init migration # migration は可変
イニシャライズで作成されたalembic.iniとenv.pyを編集する
# ~~
sqlalchemy.url = mysql+pymysql://root:%(MYSQL_ROOT_PASSWORD)s@db/qiita_copy
# ~~
# ~~~
import os #追加
from api.v1.db import Base #追加
from api.v1.models.user import User #追加
from api.v1.models.post import Post #追加
from api.v1.models.lgtm import Lgtm #追加
# ~~~
def run_migrations_online():
config.set_section_option("alembic", "MYSQL_ROOT_PASSWORD", os.environ.get("MYSQL_ROOT_PASSWORD"))
url = config.get_main_option("sqlalchemy.url")
connectable = engine_from_config(
config.get_section(config.config_ini_section),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
url=url,
connection=connection,
target_metadata=target_metadata
)
with context.begin_transaction():
context.run_migrations()
# ~~~
これでOK
マイグレーション
まずはマイグレーレーションファイルを作成
poetry run alembic revision --autogenerate -m {ファイル名}
作成したマイグレーションを実行
poetry run alembic upgrade head
これでMYSQLにそれぞれのテーブルが作成される。
※マイグレーションの巻き戻し
poetry run alembic downgrade base
おかしくなっちゃった時は
マイグレーションのバージョン管理は設定したDatabaseのalembic_versionテーブルで保存されている。
なのでdbコンテナの中に入って、alembicテーブルのレコードを削除する。
docker-compose exec db bash
mysql -uroot -h db -p qiita_copy
delete from alembic_version;
で、migration/versionsに保存されているマイグレーションファイルを全削除すれば初期状態に戻る。
これでDBとの接続からDBに設定を流し込むところまでできた。
あとはCrudを作って割り当てればAPI側の設定はOKかな。