#SQLModelとは
公式はこちら
現在PythonのWebFrameworkで最も注目されている(?)FastAPIの作者tiangolo氏による新しいPythonのORMである。
###特徴
Pythonの型付けを強力にサポートするPydanticと、有名なORMのSQLAlchemyをベースにラップしたもので、直感的で短いコードが書けてSQLAlchemyとの互換性も優れているようで、平たく言うと今までデータベースのスキーマをPydanticで定義していたが、SQLAlchemyとFastAPIを使う場合は不要になったということ(だろう)。
早速試してみました。
環境 Ubuntu20.04 Pipenv Python3.8.10 MySQL8.0 VScode
###インストール
pipenv install fastapi sqlmodel uvicorn
とやるも...
Creating a Pipfile for this project...
Installing fastapi...
Adding fastapi to Pipfile's [packages]...
✔ Installation Succeeded
Installing sqlmodel...
Adding sqlmodel to Pipfile's [packages]...
✔ Installation Succeeded
Installing uvicorn...
Adding uvicorn to Pipfile's [packages]...
✔ Installation Succeeded
Pipfile.lock not found, creating...
Locking [dev-packages] dependencies...
Locking [packages] dependencies...
Building requirements...
Resolving dependencies...
✘ Locking Failed!
ぐぬぬ。。。依存関係の問題でLockfileを作れていない。。。
Hint: try $ pipenv lock --pre if it is a pre-release dependency.
と、あるので
/dev/python_code$ pipenv lock --pre
Locking [dev-packages] dependencies...
Locking [packages] dependencies...
Building requirements...
Resolving dependencies...
✔ Success!
Updated Pipfile.lock (d6534a)!
できた!
##FastAPIによりサーバを起動。
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
からのコマンド
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [3921] using statreload
INFO: Started server process [3923]
INFO: Waiting for application startup.
INFO: Application startup complete.
サーバ起動を確認。(実はuvicornのエラーが出たが、pipenv shell で解決)
##DBに接続する
MySQLを用意するところは割愛します。私はAWSのEC2・linuxインスタンスにMySQLを立てています。接続情報が一部異なるだけで、ローカルで立てても公式通りにsqliteを使用しても問題ないです。
ここからは公式に沿ってSQLModelを使用してみます。
以下のカラムを定義します。
・id(int)
・name(str)
・nick_name(str)
・age(int)
データを以下のように格納したいとします。
id | name | nick_name | age |
---|---|---|---|
1 | 朝倉未来 | 路上の伝説 | 29 |
2 | 朝倉海 | 海ぴょん | 28 |
3 | 齋藤光 | シバター | 36 |
まずはスキーマを定義します。
from typing import Optional
from sqlmodel import Field, SQLModel
class fighters(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
Python3.6より導入された型ヒントが用いられています。
fightersクラスはSQLModelを継承しており、PydanticのValidationが機能し、[id]と[age]にはオプションでint型を、nameとsecret_nameには強制的にstr型が入ります。
##DBにデータを格納する
上記で書いたテーブルとデータをDBへ格納します。
from typing import Optional
from sqlmodel import Field, SQLModel, create_engine, Session
class fighters(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
#1.fightersのインスタンスを作成します。
fighter_1 = fighters(name="朝倉未来", secret_name="路上の伝説", age=29)
fighter_2 = fighters(name="朝倉海", secret_name="海ぴょん")
fighter_3 = fighters(name="斎藤光", secret_name="シバター", age=35)
#2.DB接続情報を作る。localhostやIPが入ります。3306は今回使用したMySQLのポートです。
url = f'mysql+://{"user名"}:{"DBのpassword"}@{"ソース"}/{"テーブル名"}'
engine = create_engine(url, echo=True)
#3.データベースを作成、セッションをはりデータをコミットします。
SQLModel.metadata.create_all(engine)
with Session(engine) as session:
session.add(fighter_1)
session.add(fighter_2)
session.add(fighter_3)
session.commit()
以下のコマンドを入力
がしかし
sqlalchemy内部でMySQLdbというモジュールをインポートしているがそれが見当たらないとのこと。
pymysqlのインストールとソースの書き換えをする。
pipenv install pymysql
で、再度
2021-11-04 00:31:26,438 INFO sqlalchemy.engine.Engine INSERT INTO fighters (name, secret_name, age) VALUES (%(name)s, %(secret_name)s, %(age)s)
2021-11-04 00:31:26,438 INFO sqlalchemy.engine.Engine [generated in 0.00077s] {'name': '朝倉未来', 'secret_name': '路上の伝説', 'age': 29}
2021-11-04 00:31:26,458 INFO sqlalchemy.engine.Engine INSERT INTO fighters (name, secret_name, age) VALUES (%(name)s, %(secret_name)s, %(age)s)
2021-11-04 00:31:26,458 INFO sqlalchemy.engine.Engine [cached since 0.02074s ago] {'name': '朝倉海', 'secret_name': '海ぴょん', 'age': None}
2021-11-04 00:31:26,493 INFO sqlalchemy.engine.Engine INSERT INTO fighters (name, secret_name, age) VALUES (%(name)s, %(secret_name)s, %(age)s)
2021-11-04 00:31:26,493 INFO sqlalchemy.engine.Engine [cached since 0.05552s ago] {'name': '斎藤光', 'secret_name': 'シバター', 'age': 35}
2021-11-04 00:31:26,523 INFO sqlalchemy.engine.Engine COMMIT
通った。
無事接続&テーブル作成できました。
###所感
・結局APIのスキーマを定義するときにPydantic使うのなら、それほどメリットはないかも。
・SQLModelはパッケージ管理にPoetry使ってるらしい。pipenvじゃなくてPoetryにしようかな。
・Mysqlとの接続方法はこれでよいのか?
・今回FastAPI関係なかったな
次回はCRUDをやります。
間違いがあれば指摘していただけると助かります。