はじめに
みんな、手うがしよう! nikkieです。
SQLModelでデータをINSERTした後の扱い方を知りました。
目次
- はじめに
- 目次
- PyCon JP 2024より「SQLModel入門」
- 公式チュートリアル「Automatic IDs, None Defaults, and Refreshing Data」
- 終わりに
PyCon JP 2024より「SQLModel入門」
FastAPIの作者(tiangolo氏)が作ったORM、SQLModel。
日本語で読める資料としては、みずきさんによる「SQLModel入門」がオススメです。
SQLModel入門の資料です!!#pyconjp2024 #pyconjp_1 https://t.co/8todkq7X4o
— みずき@PjM, PdM学び中 (@mizzsugar0425) 2024年9月28日
まずこちらを通読し、その後公式のチュートリアルに取り組みました。
その中で知ったことを綴ります。
トピックとしては「基本的なデータの作成方法」(スライド47)
session
にデータをadd
してcommit
した後、データにアクセスすると(print
する例)
内部的に期限切れとして認識されており、refreshされるまではNoneが返される。(スライド46)
スライド47ではcommit
した後にrefresh
することでデータにアクセスできると説明されます。
with Session(engine) as session: session.add(hero_1) session.commit() print("Hero1: ", hero_1) # hero_1はNoneとして評価される session.refresh(hero_1) print("Hero1: ", hero_1) # hero_1はデータを指す
公式チュートリアル「Automatic IDs, None Defaults, and Refreshing Data」
公式チュートリアルはSQLiteを使って進みます1。
途中にあった「テーブルの作成はスクリプトで2」というトピックが興味深かったですが、この記事ではテーブルができた後のデータのINSERTを扱います。
「Automatic IDs, None Defaults, and Refreshing Data」で、みずきさん資料と同様のコードが出てきます。
Hero
インスタンスをsession
にadd
してcommit
した後、
https://sqlmodel.tiangolo.com/tutorial/automatic-id-none-refresh/#commit-the-changes-to-the-database
And now, something unexpected happens, look at the output, it seems as if the Hero instance objects had no data at all:
Hero
インスタンスを指していた変数はNone
として評価されています(automatic expiration)。
属性にアクセスすることでrefreshされると続きます
By accessing the attribute, that triggers a lot of work done by SQLModel (actually SQLAlchemy) underneath to refresh the data from the database, set it in the object's id attribute,
公式チュートリアルをベースにしたスクリプトを動かして確認しました。
uv run
などPEP 723(inline script metadata)をサポートしたツールで動かしています(SQLModelはバージョン 0.0.22)
echo=True
による出力を見ても
After commit:
の前はDBへのアクセスはなしAfter commit (access id):
の前、SELECT文が発行されている
SELECT hero.id AS hero_id, hero.name AS hero_name, hero.secret_name AS hero_secret_name, hero.age AS hero_age FROM hero WHERE hero.id = ?
?
には(1,)
と渡るようです。
(hero_1
のid
が1
というのは、どこが知っている情報なんだろう?)
終わりに
SQLModelでSession
を使ってデータをINSERTした時のauto expirationについて見てきました。
with Session(engine) as session: session.add(hero_1) session.commit() # auto expiration (hero_1自体を評価するとNone) # hero_1の属性にアクセスするか、sessionをrefreshする hero_1.id session.refresh(hero_1)
session.commit()
でSession
にadd
した変数の指すデータが変わって見えるのは副作用っぽさもあり独特だなと思います(クセが強いとこかも)。
属性アクセスまたは明示的なSession
でrefresh
するという扱い方を完全理解です!