Open12

FastAPIを勉強する

winnie279winnie279

Schemaについて

winnie279winnie279

再帰的な型定義クラスが書けない。

from pydantic import BaseModel

class Item(BaseModel):
    id: int
    name: str
    # クラス内で自身を使用できない。クラス変数なので`self`も使用できない。
    children: list[Item] = []  # NameError: name 'Item' is not defined

以下のように、クラス名をクォーテーションで囲んで文字列にする[1][2]ことで解決できる。

  from pydantic import BaseModel
  
  class Item(BaseModel):
      id: int
      name: str
-   # クラス内で自身を使用できない。クラス変数なので`self`も使用できない。
-   children: list[Item] = []  # NameError: name 'Item' is not defined
+   children: list["Item"] = []
脚注
  1. https://docs.pydantic.dev/usage/postponed_annotations/#self-referencing-models ↩︎

  2. https://github.com/tiangolo/fastapi/issues/855 ↩︎

winnie279winnie279

main.pyで受け取る型とcrud.pyで受け取る型が異なる場合[1]はどのように型を定義するべきか?

例えば以下の場合だと、アイテムを登録するユーザーのIDを自動で入れたいため型の定義が変わってしまう。

schemas.py
from pydantic import BaseModel

ItemMainCreate(BaseModel):
  name: str

ItemCrudCreate(BaseModel):
  name: str
  owner_id: str

ItemCrudCreateowner_idをオプショナルにする方法が考えられるが、値が絶対に上書きされてしまうowner_idが存在するのは気持ち悪い。

以下のようにcrud.pyowner_idを別途引数として受け取る手もあるが、項目が増えると煩雑になってしまう。

crud.py
def create_item(item: schemas.ItemMainCreate, owner_id: int):
    return {**item.dict(), "owner_id": owner_id}

今のところ項目が増える予定はないので後者の方法で実装している。
項目が増えたらそのとき考えればいいや。

脚注
  1. SQL (Relational) Databases - FastAPI ↩︎

winnie279winnie279

htmlコンテンツ?を受け取れない

音声を上手く受け取れなかった

winnie279winnie279

ユーザー認証について

winnie279winnie279

OAuth2PasswordBearerについて

OAuth2PasswordBearerのインスタンスをパスオペレーション関数にDependsとして引き渡すだけでは、トークンの整合性は確認されない。自前でJWTトークンから値を取り出して整合性を確認する必要がある。

winnie279winnie279

CRUDについて

winnie279winnie279

FastAPIのドキュメントに記載されている[1]ように、スキーマの値は次のようにDBモデルに代入すると楽。

crud.py
def create_item(db: Session, item: schemas.ItemCreate):
    db_item = models.Item(**item.dict())
    db.add(db_item)
    db.commit()
    db.refresh(db_item)
    return db_item

FastAPIのドキュメントには(たぶん)記載されていないが、DBモデルを更新するときには辞書のupdate[2]を使うと楽。
できませんでした。誰かこんな感じのやり方教えて。

crud.py
def update_item(db: Session, item_id: int, item: schemas.ItemCreate):
    db_item = get_user(db=db, item_id=item_id)
    db_item.update(**item.dict())
    db.commit()
    db.refresh(db_item)
    return db_item
脚注
  1. https://fastapi.tiangolo.com/ja/tutorial/sql-databases/#crud-utils ↩︎

  2. https://qiita.com/tag1216/items/455cf12d944967c00241 ↩︎