概要
Pythonアプリで、SQLAlchemyとAlembicを利用してMySQLのDBを利用しています。
DateTime型のカラムupdate_date
をレコード更新時の「現在時刻」にする方法を紹介します。
うまく認識されなかったケースもあったのでそちらも併せて記載します。
前提
db:mysql8.0
python:3.12
alembic:1.13.2
SQLAlchemy:2.0.3
デフォルト値を挿入時の現在時刻にする方法は以下の記事で紹介しました
マイグレーションファイルに認識されなかった例
以下のようにモデルを定義したとします。
class SampleTable(Base):
__tablename__ = 'sample_table'
id = Column(Integer, primary_key=True, autoincrement=True)
created_at = Column(DateTime, nullable=False, server_default=func.now())
update_date = Column(DateTime, nullable=False, server_default=func.now(), onupdate=func.now())
しかし、これでalembic revision --autogenerate
を実行しても、マイグレーションファイルで「onupdate=func.now()
」の部分が認識されませんでした。
onupdate=func.now()
は、SQLAlchemyのモデル定義としては正しいオプションだと思うのですが、Alembicのマイグレーションファイルではこの情報を反映してくれないようです。
マイグレーションファイルに認識された例
以下のようにモデル定義を変更しました。
SQL文のCURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
をそのまま指定してあげる方法です。
class SampleTable(Base):
__tablename__ = 'sample_table'
id = Column(Integer, primary_key=True, autoincrement=True)
created_at = Column(DateTime, nullable=False, server_default=func.now())
update_date = Column(DateTime, nullable=False, server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))
これでalembic revision --autogenerate
を実行すると、マイグレーションファイルのupdate_date
では、以下のようにSQLが認識されています。
op.add_column('sample_table', sa.Column('update_date', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), nullable=False))
上記でマイグレートすると、期待通りに、レコード更新時の現在時刻が入るようになりました。
SQLAlchemyとAlembicを使う場合「上記の方法が一番好ましいのか?」はわかりませんが、これであればやりたいことは実現できました。
以上です!