Goalist Developers Blog

SQLAlchemyでsetattrしたのにupdateされない

こんにちは ゴーリスト開発のモリツグです

最近ちょっとずつPythonを触り始めたひよっこです。
Python3.6でSQLAlchemyを使っていて何故かupdateが行われない現象に悩まされたので、原因と対処法をメモしておこうと思います。

ぶちあたった問題

sessionの取得やcommit flush closeあたりは適切に行われているものとして省略します。 あとPythonなのにキャメル記法なのは一旦みなかったことにしてください。

・・・(sessionの取得)・・・

# 更新したいレコードを取得
dbAccount = session.query(Account) 
    .filter(Account.id == account.id) 
    .first()

# 更新したい値を持っているaccountからdbAccount へ値をコピーして反映
for key, value in account.__dict__.items():
    if callable(value) == False: # 関数は省く
        setattr(dbAccount, key, value)

・・・(commit flush closeの処理)・・・

上記のようなソースコードを書いた場合、デバッガ上ではdbAccount の値が更新されているのに、DB上の値は更新されません。
試行錯誤した結果、setattrのvalueをちゃんとキャストしてやるとDB上の値も更新されました。

# 更新したい値を持っているaccountからdbAccount へ値をコピーして反映
for key, value in account.__dict__.items():
    if callable(value) == False: # 関数は省く
        # setattr(dbAccount, key, value) # valueの型を判定してキャスト
        if isinstance(value, int):
            setattr(updateEntity, key, int(value))
        elif isinstance(value, str):
            setattr(updateEntity, key, str(value))
    ・・・(それ以外の型の処理)・・・

何故こんなことになっているのか、詳しい理由は不明ですが、きっと何か深淵なる理由があるのだと思います。