2023年6月28日水曜日

SQLAlchemyでautomapを使う

SQLAlchemyでautomapを使う

概要

過去に既存のテーブルに対して操作する方法を紹介しました
その際には自分でモデルを作成し操作しています
今回はモデル自体を自動で生成できる automap という機能を紹介します

環境

  • macOS 13.4.1
  • Python 3.11.3
  • sqlalchemy 2.0.17
  • PyMySQL 1.1.0

テーブル作成

なんでも OK です

CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(50),
  `age` int,
  `profile` varchar(50),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

INSERT INTO user VALUES (null, 'hawk', 10, 'ruby,sinatra');
INSERT INTO user VALUES (null, 'snowlog', 20, 'python,flask');
INSERT INTO user VALUES (null, 'hawksnowlog', 30, 'swift,realm');

automap サンプルコード

MySQL クライアントは今回 pymysql を使っているのでエンジン作成の際に pymysql を指定します

  • vim app.py
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine

# automap を使用するための準備
Base = automap_base()

# エンジンの作成
engine = create_engine("mysql+pymysql://root@localhost/test?charset=utf8mb4")

# テーブル定義の読み込み
Base.prepare(autoload_with=engine)

# user テーブルから user モデルの抽出
User = Base.classes.user

# CRUD 用セッションの作成
session = Session(engine)

# ex) データ登録
session.add(User(name="test", age=99, profile="golang,gin"))
session.commit()

# ex) データ全件取得
users = session.query(User).all()
for user in users:
    print (user.name)

ポイントは Base.prepare の部分になります
モデルを自分で定義する際は declarative_base を使いますが automap の場合は prepare(autoload_with=engine) を使います

メリット・デメリット

メリットとしてはモデルを自分で定義する必要がないので簡単です
デメリットとしては抽出したモデルはクラスとして定義していないのでタイプヒントなどに使えません
また pyright などを使っている場合は抽出したモデルのフィールドやメソッド情報が pyright 側に伝わらないので補完も使えなくなります

automap で自動抽出したモデルからクラスを再定義する方法があるのか気になりました

最後に

SQLAlchemy の automap を使ってみました
ユースケースとしてはすでにあるテーブルに対するツールやライブラリを作成したいときに使う感じかなと思います
モデルを自分で定義するケースはまだテーブルなどがなくマイグレーションも行いたい場合にはモデルを自分で定義したほうが絶対にきれいになります

既存のテーブルに対して automap を使って将来的にマイグレーションスクリプトまで管理したい場合にはどうすれrばいいのかも気になりました

参考サイト

0 件のコメント:

コメントを投稿