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
が出ます
参考