承認された回答のコメントで重要な問題を明確にする例
自分でいじってみないとわからなかったので、戸惑う人もいると思いました。あなたがだれで、いつあなたが始めたのかを考えているid == 6
とno_of_logins == 30
しましょう。
# 1 (bad)
user.no_of_logins += 1
# result: UPDATE user SET no_of_logins = 31 WHERE user.id = 6
# 2 (bad)
user.no_of_logins = user.no_of_logins + 1
# result: UPDATE user SET no_of_logins = 31 WHERE user.id = 6
# 3 (bad)
setattr(user, 'no_of_logins', user.no_of_logins + 1)
# result: UPDATE user SET no_of_logins = 31 WHERE user.id = 6
# 4 (ok)
user.no_of_logins = User.no_of_logins + 1
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6
# 5 (ok)
setattr(user, 'no_of_logins', User.no_of_logins + 1)
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6
ポイント
インスタンスの代わりにクラスを参照することで、SQLAlchemyをインクリメントについてより賢くし、Python側ではなくデータベース側でそれを行うことができます。データ破損の影響を受けにくいため、データベース内で実行することをお勧めします(たとえば、2つのクライアントが同時にインクリメントしようとすると、最終的に2つではなく1つしかインクリメントされません)。ロックを設定したり、分離レベルを上げたりすると、Pythonでインクリメントを行うことが可能だと思いますが、なぜそうする必要がないのでしょうか。
注意点
のようなSQLを生成するコードを介して2回インクリメントSET no_of_logins = no_of_logins + 1
する場合は、コミットするか、少なくともインクリメント間でフラッシュする必要があります。そうしないと、合計で1つのインクリメントしか取得できません。
# 6 (bad)
user.no_of_logins = User.no_of_logins + 1
user.no_of_logins = User.no_of_logins + 1
session.commit()
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6
# 7 (ok)
user.no_of_logins = User.no_of_logins + 1
session.flush()
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6
user.no_of_logins = User.no_of_logins + 1
session.commit()
# result: UPDATE user SET no_of_logins = no_of_logins + 1 WHERE user.id = 6