SQLAlchemy で get, set する列を動的に指定する方法。
環境
-
Windows 10
-
Python 3.8
-
SQLAlchemy 1.4.54
$ pip freeze greenlet==3.1.1 SQLAlchemy==1.4.54
結論
-
getattr
,setattr
を使い、属性名を動的に指定できる - 属性名として、
Column.key
を使用できる
デモ
Chat-GPT 4o の出力を少し改変した。
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base
# SQLite用のエンジン(実際のアプリでは適宜変更)
engine = create_engine("sqlite:///:memory:", echo=True)
SessionLocal = sessionmaker(bind=engine)
# モデル定義
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(50), nullable=False)
email = Column(String(100), nullable=False)
def __repr__(self):
return f"<User(id={self.id}, name={self.name}, email={self.email})>"
# テーブル作成
Base.metadata.create_all(engine)
# セッション作成
session = SessionLocal()
users = [User(), User()]
users[0].id = 1
users[0].name = "Alice"
users[0].email = "alice@example.com"
users[1].id = 2
users[1].name = "Bob"
users[1].email = "bob@example.com"
session.add_all(users)
session.commit()
# 例として2つのUserを取得 (仮に存在するとする)
user_a = session.query(User).filter_by(id=1).one()
user_b = session.query(User).filter_by(id=2).one()
# User.email のカラムオブジェクト
col = User.email
# `setattr()` を使用して動的に代入
setattr(user_a, col.key, getattr(user_b, col.key))
# 変更をコミット
session.commit()
# 結果確認
updated_user_a = session.query(User).filter_by(name="Alice").one()
print(updated_user_a) # email が "bob@example.com" に変更されているはず
デモ出力のプロンプト
sqlalchemy1.4のmodelクラスを1つ例示してください。
session.query()
を使用して、User のインスタンスを2つ (user_a, user_b とする) 取得したとします。ここで、user_bのメールアドレスをuser_aにコピーしたければ、通常はuser_a.email = user_b.email
のように email 属性を使用するとすると思います。ですがcol = User.email
を使用してuser_a[col] = user_b[col]
のようにしたいです。できますか。
作ってもらった例をデモとして動かしたいので、テーブルを作成するコードも追加してもらえますか。
※レコードを作成するコードは、最後の質問をする前に自分で作っていたので依頼しなかった。