SQLAlchemyでテーブルクラスを作るときに、既存のテーブル情報を使って動的に作り出したいニーズがあって、ややハマったので方法をメモしておきます。
普通の作り方
公式ドキュメントなどでは、既存のuserテーブルにマッピングするUserクラスはこのような作り方が紹介されています。declaratibe_baseという機能を使うことで、__tablename__で指定したテーブルと自動的にマッピングが作られるというわけです。
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import declarative_base
# declarative base class
Base = declarative_base()
# an example mapping using the base
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
name = Column(String)
fullname = Column(String)
nickname = Column(String)
今回やりたかったこと
-
__tablename__の部分を可変にしたい - 属性として持つ
Columnを既存のテーブルに合わせて可変にしたい
対象のテーブル名を切り替えながらいろいろ処理する機能が作りたかったということです
# create_engineのところは省略
bind = create_engine(...)
Base = declarative_base(bind)
name = ここに既存のテーブル名を指定
namespace = {
'__tablename__': name,
'__table_args__': {'autoload': True},
}
class_ = type('TableClass', (Base,), namespace)
これで最初の例と同様のテーブルクラスが作成できます
typeの第一引数の'TableClass'という名前は適当です
型を確認するとBaseを継承して作った場合と同じです
print(type(class_))
<class 'sqlalchemy.orm.decl_api.DeclarativeMeta'>
varsで内容を見るとテーブルに存在する列情報のほか、__mapper__属性もあります
補足
指定したテーブルが存在しないとsqlalchemy.exc.NoSuchTableErrorが出ます
参考