定義(pyproject.toml や models.py)から、メインのAPI処理(app/main.py)まで書いてみる。
【構成】
project/
├── pyproject.toml # ライブラリの定義
├── alembic.ini # DBマイグレーション設定
├── migrations/ # マイグレーションファイル(自動生成)
├── src/ # 自作ライブラリ(コアロジック)
│ └── core/
│ ├── __init__.py
│ ├── models.py # DBテーブル定義
│ └── engine.py # SP計算ロジック
└── app/ # FastAPI本体
└── main.py
ライブラリの定義
project.toml
[build-system]
requires = ["setuptools>=61.0"] #setuptoolsのversion61.0を使う
build-backend = "setuptools.build_meta" #バッグエンド作業担当
[project]
name = "core"
version = "0.1.0"
description = "コアエンジン"
dependencies = [
"fastapi",
"uvicorn",
"sqlalchemy",
"alembic",
"pydantic",
"pydantic-settings"
]
[tool.setuptools.packages.find]
where = ["src"] # パッケージはsrc配下
models.py
from sqlalchemy import Column,Integer,String,Float
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class Player(Base):
__tablename__ = "players" # DB内でのテーブル名
id = Column(Integer,primary_key=True,index=True)
name = Column(String,unique=True)
sp = Column(Float,default=100.0)
level = Column(Integer,default=1)
ライブラリのインストール
pip install -e .
※pyproject.tomlと同じ階層にsrcが存在しないとエラーになります。
DBマイグレーションの自動化(Alembic) の準備
Alembicの初期化
alembic init migrations
alembic.iniの修正
SQLiteを使ってmyproject.dbという名前のDBファイルを作る
;sqlalchemy.url = driver://user:pass@localhost/dbname
sqlalchemy.url = sqlite:///./myproject.db
__file__:今いるところ
dirname:そのファイルが入っているフォルダ
abspath:相対的な場所
sys.path:絶対的な場所
env.py
import sys
from os.path import abspath,dirname
sys.path.insert(0,abspath(dirname(dirname(__file__)))) #パスを通す
# 自作ライブラリからBaseをインポート
from core.models import Base
#書き換える
# target_metadata = None
target_metadata = Base.metadata
設計図の作成
”--autogenerate”は、models.pyにはテーブルが設定されているのに
実際のデータベースにはまだないという差分を見つけ出します。
.bash
alembic revision --autogenerate -m "create player table"
migrations/versions/の中にテーブルを作る
マイグレーションに関する台本(スクリプト)は migrations というフォルダに入れる
alembic.ini
script_location = %(here)s/migrations
migrations/env.py
config = context.config
migrationsとversionsをくっつけている。
alembic.script.base.ScriptDirectory
https://github.com/sqlalchemy/alembic/blob/7b510dc52c7e931f393b6387f183bf888a08dee9/alembic/script/base.py
env.py 内の context オブジェクトに、保存先のフォルダ情報が渡される。
env.py
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
設計図をDBに適用(=マイグレート)
.bash
alembic upgrade head
メインファイル作成
自作ライブラリ(core)をインポートして,DBと連携する。
app/main.py
from fastapi import FastAPI, Depends
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session
from asagaya_core.models import Player # 自作ライブラリから呼び出し!
# 1. DB接続の設定
SQLALCHEMY_DATABASE_URL = "sqlite:///./myproject.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
app = FastAPI()
# 2. DBセッションの管理(Djangoの connection みたいなもの)
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# 3. エンドポイント(APIの窓口)
@app.get("/")
def read_root():
return {"message": "ようこそ"}
@app.get("/players")
def get_players(db: Session = Depends(get_db)):
# DBから全プレイヤーを取得
players = db.query(Player).all()
return players
動作確認(pyproject.toml配下で)
.bash
uvicorn app.main:app --reload
ブラウザ
http://127.0.0.1:8000/
上だとDBにデータが空なので、
app/main.py
from fastapi import Body
# --- 既存のコードの下に ---
@app.post("/players")
def create_player(name: str = Body(...), db: Session = Depends(get_db)):
new_player = Player(name=name, sp=100.0, level=
db.add(new_player)
db.commit()
db.refresh(new_player) # DBで発行されたIDなどを読み込み直す
return {"message": "プレイヤーを登録しました", "player": new_player}
