Tech Blog

full-stack-fastapi-templateのコードリーディング

full-stack-fastapi-templateはFastAPI公式から提供されているFastAPI+Reactによるサンプルアプリです。バックエンド部分を中心にコードリーディングの記録を残します(随時更新)

8/19/2024

APIエンドポイント

/app/api/main.pyで次のように4つのサブルーターを統合している。

api_router = APIRouter()
api_router.include_router(login.router, tags=["login"])
api_router.include_router(users.router, prefix="/users", tags=["users"])
api_router.include_router(utils.router, prefix="/utils", tags=["utils"])
api_router.include_router(items.router, prefix="/items", tags=["items"])

tags=["login"]のように、タグ付けすることでSwaggerUI上でタグごとにパスが表示されるようになる。

backend/routers以下で各ルーターを定義。

/signup

  • メールアドレス、パスワード、氏名で新規ユーザー登録をする。

user_create = UserCreate.model_validate(user_in)
として、UserRegisterインスタンスからUserCreateインスタンスを作る
(UserCreateのみが持つis_active属性とis_superuser属性はデフォルトでそれぞれ、is_active=True,is_superuser=Falseが割り当てられる。 )

設定情報

Pydantic Settingsを使用することでBaseSettingsを継承したクラスの中で環境変数を読み取って、型アノテーションを使用した検証、管理ができる。

環境変数はbackendディレクトリと同階層にある.envに記述して

Basesettingsクラスを継承したapp/api/core.pySettingsクラスで

    model_config = SettingsConfigDict(
        # Use top level .env file (one level above ./backend/)
        env_file="../.env",
        env_ignore_empty=True,
        extra="ignore",
    )

のように環境変数を読み取って、
設定情報を記述している

  • 他のファイルでSettingsクラスで定義した設定用変数を使用する手順

    1. config.pyでsettings = Settings()としてインスタンスを生成
    2. 設定情報を使用するファイルの中で、from app.core.config import settingsとしてインポート
    3. 以下のようにsettings.(変数名)という形で記述する。
    user_in = UserCreate(
        email=settings.FIRST_SUPERUSER_EMAIL,
        password=settings.FIRST_SUPERUSER_PASSWORD,
        is_superuser=True,
        user_name=settings.FIRST_SUPERUSER_NAME,
    )
    

このようにすることで、Settingsクラスで定義した設定値に簡単にアクセスできる。

参考:

https://zenn.dev/nowa0402/articles/47e3edb0e93380https://zenn.dev/nowa0402/articles/47e3edb0e93380

モデル定義

app/models.pyに記述している。

例えば、ORMにSQLAlchemyを使う場合はSQLAlchemyモデルとPydanticモデルの2つを定義する必要がある。

しかし、SQLModelの場合は公式ドキュメント
にあるように、SQLModelモデルはPydanticモデルとSQLAlchemyモデルを兼ねており、1箇所で定義すればよいので冗長性を減らすことができる。

class User(UserBase, table=True):
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    hashed_password: str
    items: list["Item"] = Relationship(back_populates="owner", cascade_delete=True)

のようにtable=trueとした場合にテーブル定義に使用される。

参考: https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/

依存性注入

app/api/deps.pyには依存性注入に使用する関数を置く

  • OAuth2による認証

OAuth2PasswordRequestFormの実装
https://github.com/fastapi/fastapi/blob/master/fastapi/security/oauth2.pyhttps://github.com/fastapi/fastapi/blob/master/fastapi/security/oauth2.py

sequenceDiagram
    participant Client as クライアント
    participant API as FastAPIサーバー
    participant DB as データベース

    Client->>API: POST /login/access-token (username, password)
    API->>DB: ユーザー情報を照会
    alt 認証成功
        DB-->>API: ユーザーオブジェクトを返す
        API->>API: ユーザーの状態を確認 (is_active)
        alt ユーザーが有効
            API->>API: トークンの有効期限を設定
            API->>API: アクセストークンを生成
            API-->>Client: アクセストークンを返す
        else ユーザーが無効
            API-->>Client: 400エラー (Inactive user)
        end
    else 認証失敗
        DB-->>API: None (ユーザーなし)
        API-->>Client: 400エラー (Incorrect email or password)
    end

参考
https://ritou.hatenablog.com/entry/20140927/1411811648https://ritou.hatenablog.com/entry/20140927/1411811648

記事へのご感想、ご意見は問い合わせフォームからお送りください。

記事一覧に戻る

My Awesome Website!