Merge branch 'master' into jsonable_encoder

This commit is contained in:
Pedro Lobato 2026-02-13 16:03:08 -05:00 committed by GitHub
commit 5179e3c467
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
104 changed files with 7025 additions and 868 deletions

View File

@ -13,6 +13,7 @@ hide:
### Translations
* 🌐 Update translations for ja (update-all). PR [#14916](https://github.com/fastapi/fastapi/pull/14916) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🌐 Update translations for pt (update-all). PR [#14912](https://github.com/fastapi/fastapi/pull/14912) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🌐 Update translations for es (update-all and add-missing). PR [#14911](https://github.com/fastapi/fastapi/pull/14911) by [@YuriiMotov](https://github.com/YuriiMotov).
* 🌐 Update translations for zh (update-all). PR [#14917](https://github.com/fastapi/fastapi/pull/14917) by [@YuriiMotov](https://github.com/YuriiMotov).

503
docs/ja/docs/_llm-test.md Normal file
View File

@ -0,0 +1,503 @@
# LLM テストファイル { #llm-test-file }
このドキュメントは、ドキュメントを翻訳する <abbr title="Large Language Model - 大規模言語モデル">LLM</abbr> が、`scripts/translate.py` の `general_prompt` と、`docs/{language code}/llm-prompt.md` の言語固有プロンプトを理解しているかをテストします。言語固有プロンプトは `general_prompt` の末尾に追加されます。
ここに追加したテストは、すべての言語固有プロンプトの設計者が参照します。
使い方:
* 言語固有プロンプトを用意します - `docs/{language code}/llm-prompt.md`
* この文書を希望するターゲット言語に新規で翻訳します(例: `translate.py``translate-page` コマンド)。これにより `docs/{language code}/docs/_llm-test.md` に翻訳が作成されます。
* 翻訳が問題ないか確認します。
* 必要であれば、言語固有プロンプト、general プロンプト、または英語ドキュメントを改善します。
* その後、翻訳に残っている問題を手動で修正し、良い翻訳にします。
* 良い翻訳を用意した状態でもう一度翻訳します。理想的な結果は、LLM が翻訳に一切変更を加えないことです。つまり general プロンプトと言語固有プロンプトが最良であることを意味します(時々いくつかランダムに見える変更を行うことがあります。理由は <a href="https://doublespeak.chat/#/handbook#deterministic-output" class="external-link" target="_blank">LLM は決定論的アルゴリズムではない</a> ためです)。
テスト内容:
## コードスニペット { #code-snippets }
//// tab | テスト
これはコードスニペットです: `foo`。そしてこれもコードスニペットです: `bar`。さらにもう一つ: `baz quux`
////
//// tab | 情報
コードスニペットの内容はそのままにしておく必要があります。
`scripts/translate.py` の general プロンプト内「### Content of code snippets」の節を参照してください。
////
## 引用 { #quotes }
//// tab | テスト
昨日、友人はこう書きました。「incorrectly を正しく綴れば、あなたはそれを間違って綴ったことになる」。それに対して私はこう答えました。「そのとおり。ただし『incorrectly』は誤りで、『"incorrectly"』ではありません」。
/// note | 備考
LLM はおそらくここを誤って翻訳します。重要なのは、再翻訳時に修正済みの翻訳を維持できるかどうかだけです。
///
////
//// tab | 情報
プロンプト設計者は、ストレートクォートをタイポグラフィックな引用符に変換するかどうかを選べます。そのままでも問題ありません。
例として `docs/de/llm-prompt.md` の「### Quotes」の節を参照してください。
////
## コードスニペット内の引用 { #quotes-in-code-snippets }
//// tab | テスト
`pip install "foo[bar]"`
コードスニペット中の文字列リテラルの例: `"this"`, `'that'`.
難しい文字列リテラルの例: `f"I like {'oranges' if orange else "apples"}"`
ハードコア: `Yesterday, my friend wrote: "If you spell incorrectly correctly, you have spelled it incorrectly". To which I answered: "Correct, but 'incorrectly' is incorrectly not '"incorrectly"'"`
////
//// tab | 情報
... ただし、コードスニペット内の引用符はそのままにしておく必要があります。
////
## コードブロック { #code-blocks }
//// tab | テスト
Bash のコード例です...
```bash
# 宇宙にあいさつを表示
echo "Hello universe"
```
...そしてコンソールのコード例です...
```console
$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting server
Searching for package file structure
```
...さらに別のコンソールのコード例です...
```console
// ディレクトリ "code" を作成
$ mkdir code
// そのディレクトリに移動
$ cd code
```
...そして Python のコード例です...
```Python
wont_work() # これは動作しません 😱
works(foo="bar") # これは動作します 🎉
```
...以上です。
////
//// tab | 情報
コードブロック内のコードは、コメントを除き、変更してはいけません。
`scripts/translate.py` の general プロンプト内「### Content of code blocks」の節を参照してください。
////
## タブと色付きボックス { #tabs-and-colored-boxes }
//// tab | テスト
/// info | 情報
いくつかのテキスト
///
/// note | 備考
いくつかのテキスト
///
/// note | 技術詳細
いくつかのテキスト
///
/// check | 確認
いくつかのテキスト
///
/// tip | 豆知識
いくつかのテキスト
///
/// warning | 注意
いくつかのテキスト
///
/// danger | 警告
いくつかのテキスト
///
////
//// tab | 情報
タブおよび `Info`/`Note`/`Warning` などのブロックには、タイトルの翻訳を縦棒(`|`)の後ろに追加します。
`scripts/translate.py` の general プロンプト内「### Special blocks」と「### Tab blocks」の節を参照してください。
////
## Web リンクと内部リンク { #web-and-internal-links }
//// tab | テスト
リンクのテキストは翻訳し、リンク先のアドレスは変更しないでください:
* [上の見出しへのリンク](#code-snippets)
* [内部リンク](index.md#installation){.internal-link target=_blank}
* <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">外部リンク</a>
* <a href="https://fastapi.tiangolo.com/css/styles.css" class="external-link" target="_blank">スタイルへのリンク</a>
* <a href="https://fastapi.tiangolo.com/js/logic.js" class="external-link" target="_blank">スクリプトへのリンク</a>
* <a href="https://fastapi.tiangolo.com/img/foo.jpg" class="external-link" target="_blank">画像へのリンク</a>
リンクのテキストは翻訳し、リンク先のアドレスは翻訳版を指すようにしてください:
* <a href="https://fastapi.tiangolo.com/ja/" class="external-link" target="_blank">FastAPI リンク</a>
////
//// tab | 情報
リンクのテキストは翻訳し、アドレスは変更しないでください。例外は、FastAPI ドキュメントのページへの絶対 URL です。その場合は翻訳版へのリンクにします。
`scripts/translate.py` の general プロンプト内「### Links」の節を参照してください。
////
## HTML "abbr" 要素 { #html-abbr-elements }
//// tab | テスト
ここでは HTML の "abbr" 要素で包まれたものをいくつか示します(いくつかは架空です):
### abbr が完全な語句を示す { #the-abbr-gives-a-full-phrase }
* <abbr title="Getting Things Done - 仕事を成し遂げること">GTD</abbr>
* <abbr title="less than - より小さい"><code>lt</code></abbr>
* <abbr title="XML Web Token - XML ウェブトークン">XWT</abbr>
* <abbr title="Parallel Server Gateway Interface - 並列サーバーゲートウェイインターフェース">PSGI</abbr>
### abbr が完全な語句と説明を示す { #the-abbr-gives-a-full-phrase-and-an-explanation }
* <abbr title="Mozilla Developer Network - Mozilla 開発者ネットワーク: 開発者向けドキュメント、Firefox の開発元が執筆">MDN</abbr>
* <abbr title="Input/Output - 入出力: ディスクの読み書き、ネットワーク通信。">I/O</abbr>.
////
//// tab | 情報
"abbr" 要素の "title" 属性は特定の指示に従って翻訳します。
翻訳は、英語の語を説明するために独自の "abbr" 要素を追加してもよく、LLM はそれらを削除してはいけません。
`scripts/translate.py` の general プロンプト内「### HTML abbr elements」の節を参照してください。
////
## HTML "dfn" 要素 { #html-dfn-elements }
* <dfn title="ある方法で接続・連携して動作するよう構成された複数のマシンの集合">クラスター</dfn>
* <dfn title="入力層と出力層の間に多数の隠れ層を持つ人工ニューラルネットワークを用いる機械学習の手法で、その内部構造を包括的に形成する">ディープラーニング</dfn>
## 見出し { #headings }
//// tab | テスト
### Web アプリを開発する - チュートリアル { #develop-a-webapp-a-tutorial }
こんにちは。
### 型ヒントとアノテーション { #type-hints-and-annotations }
またこんにちは。
### スーパークラスとサブクラス { #super-and-subclasses }
またこんにちは。
////
//// tab | 情報
見出しに関する唯一の厳格なルールは、リンクが壊れないように、LLM が中括弧内のハッシュ部分を変更しないことです。
`scripts/translate.py` の general プロンプト内「### Headings」の節を参照してください。
言語固有の指示については、例として `docs/de/llm-prompt.md` の「### Headings」の節を参照してください。
////
## ドキュメントで使う用語 { #terms-used-in-the-docs }
//// tab | テスト
* you
* your
* e.g.
* etc.
* `foo``int` として
* `bar``str` として
* `baz``list` として
* チュートリアル - ユーザーガイド
* 上級ユーザーガイド
* SQLModel ドキュメント
* API ドキュメント
* 自動生成ドキュメント
* データサイエンス
* ディープラーニング
* 機械学習
* 依存性注入
* HTTP Basic 認証
* HTTP Digest
* ISO 形式
* JSON Schema 規格
* JSON スキーマ
* スキーマ定義
* Password Flow
* モバイル
* 非推奨
* 設計された
* 無効
* オンザフライ
* 標準
* デフォルト
* 大文字小文字を区別
* 大文字小文字を区別しない
* アプリケーションを提供する
* ページを配信する
* アプリ
* アプリケーション
* リクエスト
* レスポンス
* エラーレスポンス
* path operation
* path operation デコレータ
* path operation 関数
* ボディ
* リクエストボディ
* レスポンスボディ
* JSON ボディ
* フォームボディ
* ファイルボディ
* 関数本体
* パラメータ
* ボディパラメータ
* パスパラメータ
* クエリパラメータ
* Cookie パラメータ
* ヘッダーパラメータ
* フォームパラメータ
* 関数パラメータ
* イベント
* 起動イベント
* サーバーの起動
* シャットダウンイベント
* lifespan イベント
* ハンドラ
* イベントハンドラ
* 例外ハンドラ
* 処理する
* モデル
* Pydantic モデル
* データモデル
* データベースモデル
* フォームモデル
* モデルオブジェクト
* クラス
* 基底クラス
* 親クラス
* サブクラス
* 子クラス
* 兄弟クラス
* クラスメソッド
* ヘッダー
* ヘッダー(複数)
* 認可ヘッダー
* `Authorization` ヘッダー
* Forwarded ヘッダー
* 依存性注入システム
* 依存関係
* dependable
* dependant
* I/O バウンド
* CPU バウンド
* 同時実行性
* 並列性
* マルチプロセッシング
* env var
* 環境変数
* `PATH`
* `PATH` 環境変数
* 認証
* 認証プロバイダ
* 認可
* 認可フォーム
* 認可プロバイダ
* ユーザーが認証する
* システムがユーザーを認証する
* CLI
* コマンドラインインターフェース
* サーバー
* クライアント
* クラウドプロバイダ
* クラウドサービス
* 開発
* 開発段階
* dict
* 辞書
* 列挙型
* Enum
* 列挙メンバー
* エンコーダー
* デコーダー
* エンコードする
* デコードする
* 例外
* 送出する
* 式
* 文
* フロントエンド
* バックエンド
* GitHub ディスカッション
* GitHub Issue
* パフォーマンス
* パフォーマンス最適化
* 戻り値の型
* 戻り値
* セキュリティ
* セキュリティスキーム
* タスク
* バックグラウンドタスク
* タスク関数
* テンプレート
* テンプレートエンジン
* 型アノテーション
* 型ヒント
* サーバーワーカー
* Uvicorn ワーカー
* Gunicorn ワーカー
* ワーカープロセス
* ワーカークラス
* ワークロード
* デプロイ
* デプロイする
* SDK
* ソフトウェア開発キット
* `APIRouter`
* `requirements.txt`
* Bearer Token
* 破壊的変更
* バグ
* ボタン
* 呼び出し可能
* コード
* コミット
* コンテキストマネージャ
* コルーチン
* データベースセッション
* ディスク
* ドメイン
* エンジン
* フェイクの X
* HTTP GET メソッド
* アイテム
* ライブラリ
* ライフスパン
* ロック
* ミドルウェア
* モバイルアプリケーション
* モジュール
* マウント
* ネットワーク
* オリジン
* オーバーライド
* ペイロード
* プロセッサ
* プロパティ
* プロキシ
* プルリクエスト
* クエリ
* RAM
* リモートマシン
* ステータスコード
* 文字列
* タグ
* Web フレームワーク
* ワイルドカード
* 返す
* 検証する
////
//// tab | 情報
これはドキュメントで見られる主に技術用語の不完全かつ規範的でない一覧です。プロンプト設計者が、LLM がどの用語で手助けを必要としているかを把握するのに役立つかもしれません。例えば、良い翻訳を最適でない翻訳に戻してしまう場合や、あなたの言語での活用・格変化に問題がある場合などです。
`docs/de/llm-prompt.md` の「### List of English terms and their preferred German translations」の節を参照してください。
////

View File

@ -0,0 +1,3 @@
# 概要 { #about }
FastAPI の概要、その設計やインスピレーションなどについて解説します。🤓

View File

@ -0,0 +1,247 @@
# OpenAPI の追加レスポンス { #additional-responses-in-openapi }
/// warning | 注意
これは比較的高度なトピックです。
FastAPI を使い始めたばかりであれば、これは不要かもしれません。
///
追加のステータスコード、メディアタイプ、説明などを伴う追加レスポンスを宣言できます。
それらの追加レスポンスは OpenAPI スキーマに含まれ、API ドキュメントにも表示されます。
ただし、それらの追加レスポンスについては、ステータスコードとコンテンツを指定して `JSONResponse` などの `Response` を直接返す必要があります。
## `model` を使った追加レスポンス { #additional-response-with-model }
*path operation デコレータ*に `responses` パラメータを渡せます。
これは `dict` を受け取り、キーは各レスポンスのステータスコード(例: `200`)、値は各レスポンスの情報を含む別の `dict` です。
それぞれのレスポンス `dict` には、`response_model` と同様に Pydantic モデルを格納する `model` キーを含められます。
FastAPI はそのモデルから JSON Schema を生成し、OpenAPI の適切な場所に含めます。
例えば、ステータスコード `404` と Pydantic モデル `Message` を持つ別のレスポンスを宣言するには、次のように書けます:
{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *}
/// note | 備考
`JSONResponse` を直接返す必要がある点に注意してください。
///
/// info | 情報
`model` キーは OpenAPI の一部ではありません。
FastAPI はそこから Pydantic モデルを取得して JSON Schema を生成し、適切な場所に配置します。
適切な場所は次のとおりです:
- `content` キーの中。これは値として別の JSON オブジェクト(`dict`)を持ち、その中に次が含まれます:
- メディアタイプ(例: `application/json`)をキーとし、値としてさらに別の JSON オブジェクトを持ち、その中に次が含まれます:
- `schema` キー。値としてモデル由来の JSON Schema を持ち、ここが正しい配置場所です。
- FastAPI はここに、スキーマを直接埋め込む代わりに OpenAPI 内のグローバルな JSON Schema への参照を追加します。これにより、他のアプリケーションやクライアントがそれらの JSON Schema を直接利用し、より良いコード生成ツール等を提供できます。
///
この *path operation* のために OpenAPI に生成されるレスポンスは次のとおりです:
```JSON hl_lines="3-12"
{
"responses": {
"404": {
"description": "Additional Response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Message"
}
}
}
},
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Item"
}
}
}
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
}
}
}
}
```
スキーマは OpenAPI スキーマ内の別の場所への参照になります:
```JSON hl_lines="4-16"
{
"components": {
"schemas": {
"Message": {
"title": "Message",
"required": [
"message"
],
"type": "object",
"properties": {
"message": {
"title": "Message",
"type": "string"
}
}
},
"Item": {
"title": "Item",
"required": [
"id",
"value"
],
"type": "object",
"properties": {
"id": {
"title": "Id",
"type": "string"
},
"value": {
"title": "Value",
"type": "string"
}
}
},
"ValidationError": {
"title": "ValidationError",
"required": [
"loc",
"msg",
"type"
],
"type": "object",
"properties": {
"loc": {
"title": "Location",
"type": "array",
"items": {
"type": "string"
}
},
"msg": {
"title": "Message",
"type": "string"
},
"type": {
"title": "Error Type",
"type": "string"
}
}
},
"HTTPValidationError": {
"title": "HTTPValidationError",
"type": "object",
"properties": {
"detail": {
"title": "Detail",
"type": "array",
"items": {
"$ref": "#/components/schemas/ValidationError"
}
}
}
}
}
}
}
```
## メインのレスポンスに追加のメディアタイプ { #additional-media-types-for-the-main-response }
同じ `responses` パラメータを使って、同一のメインレスポンスに別のメディアタイプを追加できます。
例えば、`image/png` の追加メディアタイプを加え、あなたの *path operation* が JSON オブジェクト(メディアタイプ `application/json`)または PNG 画像を返せることを宣言できます:
{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *}
/// note | 備考
画像は `FileResponse` を使って直接返す必要がある点に注意してください。
///
/// info | 情報
`responses` パラメータで明示的に別のメディアタイプを指定しない限り、FastAPI はレスポンスがメインのレスポンスクラスと同じメディアタイプ(デフォルトは `application/json`)であるとみなします。
ただし、メディアタイプが `None` のカスタムレスポンスクラスを指定している場合、モデルが関連付けられた追加レスポンスには FastAPI は `application/json` を使用します。
///
## 情報の結合 { #combining-information }
`response_model`、`status_code`、`responses` パラメータなど、複数の場所からのレスポンス情報を組み合わせることもできます。
`response_model` を宣言し、デフォルトのステータスコード `200`(必要なら任意のコード)を使い、その同じレスポンスに対する追加情報を `responses` で OpenAPI スキーマに直接記述できます。
FastAPI は `responses` にある追加情報を保持し、モデルの JSON Schema と結合します。
例えば、Pydantic モデルを用い、独自の `description` を持つステータスコード `404` のレスポンスを宣言できます。
さらに、`response_model` を使うステータスコード `200` のレスポンスに独自の `example` を含めることもできます:
{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *}
これらはすべて結合されて OpenAPI に含まれ、API ドキュメントに表示されます:
<img src="/img/tutorial/additional-responses/image01.png">
## 事前定義レスポンスとカスタムの組み合わせ { #combine-predefined-responses-and-custom-ones }
多くの *path operations* に適用できる事前定義のレスポンスを用意しつつ、各 *path operation* ごとに必要なカスタムレスポンスと組み合わせたい場合があります。
そのような場合、Python の `**dict_to_unpack` による `dict` の「アンパック」テクニックを使えます:
```Python
old_dict = {
"old key": "old value",
"second old key": "second old value",
}
new_dict = {**old_dict, "new key": "new value"}
```
ここでは、`new_dict` には `old_dict` のすべてのキーと値に加え、新しいキーと値が含まれます:
```Python
{
"old key": "old value",
"second old key": "second old value",
"new key": "new value",
}
```
このテクニックを使うと、*path operations* で事前定義レスポンスを再利用し、さらにカスタムのレスポンスを組み合わせられます。
例えば:
{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *}
## OpenAPI レスポンスの詳細 { #more-information-about-openapi-responses }
レスポンスに正確に何を含められるかは、OpenAPI 仕様の次のセクションを参照してください:
- <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object" class="external-link" target="_blank">OpenAPI の Responses Object</a>。ここには `Response Object` が含まれます。
- <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object" class="external-link" target="_blank">OpenAPI の Response Object</a>。`responses` パラメータ内の各レスポンスに、ここで定義されている要素を直接含められます。`description`、`headers`、`content`(ここで異なるメディアタイプや JSON Schema を宣言します)、`links` など。

View File

@ -16,7 +16,7 @@
{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *}
/// warning | 注意
/// warning
上の例のように `Response` を直接返すと、それはそのまま返されます。
@ -38,4 +38,4 @@
追加のステータスコードとレスポンスを直接返す場合、それらは OpenAPI スキーマAPI ドキュメントには含まれません。FastAPI には、事前に何が返されるかを知る方法がないからです。
しかし、[Additional Responses](additional-responses.md){.internal-link target=_blank} を使ってコード内にドキュメント化できます。
しかし、[追加のレスポンス](additional-responses.md){.internal-link target=_blank} を使ってコード内にドキュメント化できます。

View File

@ -0,0 +1,163 @@
# 高度な依存関係 { #advanced-dependencies }
## パラメータ化された依存関係 { #parameterized-dependencies }
これまで見てきた依存関係は、固定の関数またはクラスでした。
しかし、多くの異なる関数やクラスを宣言せずに、その依存関係にパラメータを設定したい場合があります。
たとえば、クエリパラメータ `q` に、ある固定の内容が含まれているかを検査する依存関係が欲しいとします。
ただし、その固定の内容はパラメータ化できるようにしたいです。
## "callable" なインスタンス { #a-callable-instance }
Python には、クラスのインスタンスを "callable" にする方法があります。
クラス自体(これはすでに callable です)ではなく、そのクラスのインスタンスです。
そのためには、`__call__` メソッドを宣言します:
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *}
この場合、この `__call__` が、**FastAPI** が追加のパラメータやサブ依存関係を確認するために使うものになり、後であなたの *path operation 関数* のパラメータに値を渡すために呼び出されるものになります。
## インスタンスのパラメータ化 { #parameterize-the-instance }
そして、`__init__` を使って、依存関係を「パラメータ化」するために利用できるインスタンスのパラメータを宣言できます:
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *}
この場合、**FastAPI** は `__init__` に触れたり気にかけたりすることはありません。私たちがコード内で直接使います。
## インスタンスの作成 { #create-an-instance }
このクラスのインスタンスは次のように作成できます:
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *}
このようにして依存関係を「パラメータ化」できます。いまや `"bar"` が属性 `checker.fixed_content` として中に保持されています。
## インスタンスを依存関係として使う { #use-the-instance-as-a-dependency }
その後、`Depends(FixedContentQueryChecker)` の代わりに `Depends(checker)` でこの `checker` を使えます。依存関係はクラスそのものではなく、インスタンスである `checker` だからです。
依存関係を解決するとき、**FastAPI** はこの `checker` を次のように呼び出します:
```Python
checker(q="somequery")
```
...そして、その戻り値を *path operation 関数* 内の依存関係の値として、パラメータ `fixed_content_included` に渡します:
{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *}
/// tip | 豆知識
ここまでの内容は回りくどく感じられるかもしれません。まだどのように役立つかが明確でないかもしれません。
これらの例は意図的に単純ですが、仕組みを示しています。
セキュリティの章では、同じやり方で実装されたユーティリティ関数があります。
ここまでを理解できていれば、そうしたセキュリティ用ユーティリティが内部でどのように動いているかも理解できています。
///
## `yield`、`HTTPException`、`except` とバックグラウンドタスクを伴う依存関係 { #dependencies-with-yield-httpexception-except-and-background-tasks }
/// warning | 注意
これらの技術的詳細は、ほとんどの場合は不要です。
主に、0.121.0 より前の FastAPI アプリケーションがあり、`yield` を使う依存関係で問題が発生している場合に有用です。
///
`yield` を使う依存関係は、さまざまなユースケースに対応し、いくつかの問題を修正するために時間とともに進化してきました。ここでは変更点の概要を説明します。
### `yield``scope` を伴う依存関係 { #dependencies-with-yield-and-scope }
バージョン 0.121.0 で、`yield` を使う依存関係に対して `Depends(scope="function")` がサポートされました。
`Depends(scope="function")` を使うと、`yield` の後の終了コードは、クライアントへレスポンスが返される前、*path operation 関数* が終了した直後に実行されます。
そして、`Depends(scope="request")`(デフォルト)を使う場合、`yield` の後の終了コードはレスポンス送信後に実行されます。
詳しくはドキュメント「[`yield` を使う依存関係 - 早期終了と `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope)」を参照してください。
### `yield``StreamingResponse` を伴う依存関係、技術詳細 { #dependencies-with-yield-and-streamingresponse-technical-details }
FastAPI 0.118.0 より前では、`yield` を使う依存関係を使用すると、*path operation 関数* が戻ってからレスポンス送信直前に終了コードが実行されていました。
これは、レスポンスがネットワーク上を移動するのを待っている間に、不要にリソースを保持しないようにする意図でした。
この変更により、`StreamingResponse` を返す場合、`yield` を持つ依存関係の終了コードはすでに実行されていることになりました。
たとえば、`yield` を持つ依存関係の中でデータベースセッションを持っていた場合、`StreamingResponse` はデータをストリーミングしている間にそのセッションを使えません。というのも、`yield` の後の終了コードでそのセッションがすでにクローズされているからです。
この挙動は 0.118.0 で元に戻され、`yield` の後の終了コードはレスポンス送信後に実行されるようになりました。
/// info | 情報
以下で見るように、これはバージョン 0.106.0 より前の挙動ととても似ていますが、いくつかのコーナーケースに対する改良とバグ修正が含まれています。
///
#### 早期終了コードのユースケース { #use-cases-with-early-exit-code }
特定の条件では、レスポンス送信前に `yield` を持つ依存関係の終了コードを実行する、古い挙動の恩恵を受けられるユースケースがあります。
例えば、`yield` を持つ依存関係でデータベースセッションを使ってユーザ検証だけを行い、その後は *path operation 関数* 内ではそのデータベースセッションを一切使わない、かつレスポンス送信に長い時間がかかる(例えばデータをゆっくり送る `StreamingResponse`)が、何らかの理由でデータベースは使わない、というケースです。
この場合、レスポンスの送信が終わるまでデータベースセッションが保持されますが、使わないのであれば保持する必要はありません。
次のようになります:
{* ../../docs_src/dependencies/tutorial013_an_py310.py *}
終了コード、すなわち `Session` の自動クローズは:
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *}
...の部分で定義されており、遅いデータ送信が終わった後に実行されます:
{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *}
しかし、`generate_stream()` はデータベースセッションを使わないため、レスポンス送信中にセッションを開いたままにしておく必要は実際にはありません。
SQLModelまたは SQLAlchemyでこの特定のユースケースがある場合は、不要になった時点でセッションを明示的にクローズできます:
{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *}
このようにすると、セッションはデータベース接続を解放するため、他のリクエストがそれを使えるようになります。
`yield` を持つ依存関係で早期終了が必要な別のユースケースがある場合は、あなたの具体的なユースケースと、なぜ `yield` を持つ依存関係の早期クローズが有益かを説明して、<a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Discussion の質問</a>を作成してください。
`yield` を持つ依存関係の早期クローズに納得できるユースケースがある場合は、早期クローズにオプトインする新しい方法を追加することを検討します。
### `yield``except` を伴う依存関係、技術詳細 { #dependencies-with-yield-and-except-technical-details }
FastAPI 0.110.0 より前では、`yield` を持つ依存関係を使い、その依存関係内で `except` によって例外を捕捉し、再度その例外を送出しなかった場合でも、その例外は自動的に送出(フォワード)され、任意の例外ハンドラまたは内部サーバエラーハンドラに渡されていました。
これは、ハンドラのないフォワードされた例外(内部サーバエラー)による未処理のメモリ消費を修正し、通常の Python コードの挙動と一貫性を持たせるため、バージョン 0.110.0 で変更されました。
### バックグラウンドタスクと `yield` を伴う依存関係、技術詳細 { #background-tasks-and-dependencies-with-yield-technical-details }
FastAPI 0.106.0 より前では、`yield` の後で例外を送出することはできませんでした。`yield` を持つ依存関係の終了コードはレスポンス送信「後」に実行されるため、[例外ハンドラ](../tutorial/handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} はすでに実行済みでした。
これは主に、依存関係が "yield" した同じオブジェクトをバックグラウンドタスク内で利用できるようにするための設計でした。終了コードはバックグラウンドタスク完了後に実行されるからです。
これは、レスポンスがネットワーク上を移動するのを待っている間にリソースを保持しないようにする意図で、FastAPI 0.106.0 で変更されました。
/// tip | 豆知識
加えて、バックグラウンドタスクは通常、独立したロジックの集合であり、(例えば専用のデータベース接続など)それ自身のリソースで個別に扱うべきです。
そのため、このやり方の方がコードはおそらくよりクリーンになります。
///
この挙動に依存していた場合は、バックグラウンドタスク用のリソースをバックグラウンドタスク内部で作成し、`yield` を持つ依存関係のリソースに依存しないデータだけを内部で使用するようにしてください。
例えば、同じデータベースセッションを使うのではなく、バックグラウンドタスク内で新しいデータベースセッションを作成し、この新しいセッションでデータベースからオブジェクトを取得します。そして、バックグラウンドタスク関数の引数としてデータベースのオブジェクト自体を渡すのではなく、そのオブジェクトの ID を渡し、バックグラウンドタスク関数内でもう一度そのオブジェクトを取得します。

View File

@ -0,0 +1,61 @@
# 高度な Python の型 { #advanced-python-types }
Python の型を扱うときに役立つ追加のアイデアをいくつか紹介します。
## `Union` または `Optional` の利用 { #using-union-or-optional }
何らかの理由で `|` が使えない場合、たとえば型アノテーションではなく `response_model=` のような場所では、縦棒(`|`)の代わりに `typing``Union` を使えます。
例えば、`str` または `None` になり得ることを宣言できます:
```python
from typing import Union
def say_hi(name: Union[str, None]):
print(f"Hi {name}!")
```
`typing` には、`None` を取り得ることを宣言するための短縮形として `Optional` もあります。
ここからは私のとても主観的な提案です:
- 🚨 `Optional[SomeType]` の使用は避けましょう
- 代わりに ✨ **`Union[SomeType, None]` を使いましょう** ✨。
どちらも等価で内部的には同一ですが、「optional任意」という語が値が任意だと誤解させやすく、実際の意味は「`None` を取り得る」であり、任意ではなく依然として必須である場合でもそうです。そのため `Optional` より `Union` を勧めます。
`Union[SomeType, None]` の方が意味がより明確だと思います。
これは用語や名前付けの話に過ぎませんが、その言葉があなたやチームメイトのコードの捉え方に影響します。
例として次の関数を見てみましょう:
```python
from typing import Optional
def say_hi(name: Optional[str]):
print(f"Hey {name}!")
```
パラメータ `name``Optional[str]` と定義されていますが、任意ではありません。このパラメータなしで関数を呼び出すことはできません:
```Python
say_hi() # あっ、これはエラーになります!😱
```
`name` パラメータにはデフォルト値がないため、依然として必須(任意ではない)です。ただし、`name` は値として `None` を受け付けます:
```Python
say_hi(name=None) # これは動作します。None は有効です 🎉
```
朗報として、多くの場合は単純に `|` を使って型の Union を定義できます:
```python
def say_hi(name: str | None):
print(f"Hey {name}!")
```
したがって、通常は `Optional``Union` といった名前を気にする必要はありません。😎

View File

@ -0,0 +1,99 @@
# 非同期テスト { #async-tests }
これまでに、提供されている `TestClient` を使って **FastAPI** アプリケーションをテストする方法を見てきました。ここまでは、`async` 関数を使わない同期テストのみでした。
テストで非同期関数を使えると、たとえばデータベースへ非同期にクエリする場合などに便利です。非同期データベースライブラリを使いながら、FastAPI アプリにリクエストを送り、その後バックエンドが正しいデータをデータベースに書き込めたかを検証したい、といったケースを想像してください。
その方法を見ていきます。
## pytest.mark.anyio { #pytest-mark-anyio }
テスト内で非同期関数を呼び出したい場合、テスト関数自体も非同期である必要があります。AnyIO はこれを実現するための便利なプラグインを提供しており、特定のテスト関数を非同期で呼び出すことを指定できます。
## HTTPX { #httpx }
**FastAPI** アプリケーションが通常の `def` 関数を使っていても、その内側は依然として `async` アプリケーションです。
`TestClient` は、標準の pytest を使って通常の `def` のテスト関数から非同期の FastAPI アプリを呼び出すための「おまじない」を内部で行います。しかし、その「おまじない」はテスト関数自体が非同期の場合には機能しません。テストを非同期で実行すると、テスト関数内で `TestClient` は使えなくなります。
`TestClient`<a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a> を基に作られており、幸いなことに API のテストには HTTPX を直接利用できます。
## 例 { #example }
簡単な例として、[大きなアプリケーション](../tutorial/bigger-applications.md){.internal-link target=_blank} と [テスト](../tutorial/testing.md){.internal-link target=_blank} で説明したものに似たファイル構成を考えます:
```
.
├── app
│   ├── __init__.py
│   ├── main.py
│   └── test_main.py
```
`main.py` は次のようになります:
{* ../../docs_src/async_tests/app_a_py310/main.py *}
`test_main.py``main.py` のテストを持ち、次のようになります:
{* ../../docs_src/async_tests/app_a_py310/test_main.py *}
## 実行 { #run-it }
テストはいつも通り次で実行できます:
<div class="termy">
```console
$ pytest
---> 100%
```
</div>
## 詳細 { #in-detail }
マーカー `@pytest.mark.anyio` は、このテスト関数を非同期で呼び出すべきであることを pytest に伝えます:
{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *}
/// tip | 豆知識
`TestClient` を使っていたときと異なり、テスト関数は `def` ではなく `async def` になっている点に注意してください。
///
次に、アプリを渡して `AsyncClient` を作成し、`await` を使って非同期リクエストを送信できます。
{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *}
これは次と同等です:
```Python
response = client.get('/')
```
...これまでは `TestClient` でリクエストを送っていました。
/// tip | 豆知識
新しい `AsyncClient` では async/await を使っている点に注意してください。リクエストは非同期です。
///
/// warning | 注意
アプリケーションが lifespan イベントに依存している場合、`AsyncClient` はそれらのイベントをトリガーしません。確実にトリガーするには、<a href="https://github.com/florimondmanca/asgi-lifespan#usage" class="external-link" target="_blank">florimondmanca/asgi-lifespan</a>`LifespanManager` を使用してください。
///
## その他の非同期関数呼び出し { #other-asynchronous-function-calls }
テスト関数が非同期になったので、FastAPI アプリへのリクエスト送信以外の `async` 関数も、コードの他の場所と同様に呼び出して(`await` して)使えます。
/// tip | 豆知識
テストに非同期関数呼び出しを統合した際に(例: <a href="https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop" class="external-link" target="_blank">MongoDB の MotorClient</a> 使用時)、`RuntimeError: Task attached to a different loop` に遭遇した場合は、イベントループを必要とするオブジェクトは非同期関数内でのみインスタンス化するようにしてください。例えば `@app.on_event("startup")` コールバック内で行います。
///

View File

@ -0,0 +1,466 @@
# プロキシの背後 { #behind-a-proxy }
多くの状況で、FastAPI アプリの前段に **Traefik****Nginx** のような**プロキシ**を置きます。
これらのプロキシは HTTPS 証明書などの処理を担います。
## プロキシの転送ヘッダー { #proxy-forwarded-headers }
アプリケーションの前段にある **プロキシ** は通常、リクエストを **サーバー** に送る前に、そのリクエストがプロキシによって転送されたことを知らせるためのヘッダーを動的に付与し、使用中の元の公開URLドメインを含むや HTTPS 使用などの情報を伝えます。
**サーバー** プログラム(例えば **FastAPI CLI** 経由の **Uvicorn**)はこれらのヘッダーを解釈し、その情報をアプリケーションに渡すことができます。
しかしセキュリティ上、サーバーは自分が信頼できるプロキシの背後にあると分からないため、これらのヘッダーを解釈しません。
/// note | 技術詳細
プロキシのヘッダーは次のとおりです:
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For" class="external-link" target="_blank">X-Forwarded-For</a>
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto" class="external-link" target="_blank">X-Forwarded-Proto</a>
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host" class="external-link" target="_blank">X-Forwarded-Host</a>
///
### プロキシ転送ヘッダーを有効化 { #enable-proxy-forwarded-headers }
FastAPI CLI を *CLI オプション* `--forwarded-allow-ips` 付きで起動し、転送ヘッダーを信頼して読んでよい IP アドレスを指定できます。
`--forwarded-allow-ips="*"` とすると、すべての送信元 IP を信頼します。
**サーバー** が信頼できる **プロキシ** の背後にあり、そのプロキシからのみ接続される場合、プロキシの IP を受け入れるようになります。
<div class="termy">
```console
$ fastapi run --forwarded-allow-ips="*"
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
### HTTPS を伴うリダイレクト { #redirects-with-https }
例えば、*path operation* `/items/` を定義しているとします:
{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *}
クライアントが `/items` にアクセスすると、既定では `/items/` にリダイレクトされます。
しかし、*CLI オプション* `--forwarded-allow-ips` を設定する前は、`http://localhost:8000/items/` にリダイレクトされる場合があります。
ですが、アプリケーションは `https://mysuperapp.com` で公開されており、`https://mysuperapp.com/items/` にリダイレクトされるべきかもしれません。
`--proxy-headers` を設定すると、FastAPI は正しい場所にリダイレクトできるようになります。😎
```
https://mysuperapp.com/items/
```
/// tip | 豆知識
HTTPS について詳しく知りたい場合は、[HTTPS について](../deployment/https.md){.internal-link target=_blank} を参照してください。
///
### プロキシ転送ヘッダーの仕組み { #how-proxy-forwarded-headers-work }
クライアントと **アプリケーションサーバー** の間で、**プロキシ** がどのように転送ヘッダーを追加するかを図示します:
```mermaid
sequenceDiagram
participant Client
participant Proxy as Proxy/Load Balancer
participant Server as FastAPI Server
Client->>Proxy: HTTPS Request<br/>Host: mysuperapp.com<br/>Path: /items
Note over Proxy: Proxy adds forwarded headers
Proxy->>Server: HTTP Request<br/>X-Forwarded-For: [client IP]<br/>X-Forwarded-Proto: https<br/>X-Forwarded-Host: mysuperapp.com<br/>Path: /items
Note over Server: Server interprets headers<br/>(if --forwarded-allow-ips is set)
Server->>Proxy: HTTP Response<br/>with correct HTTPS URLs
Proxy->>Client: HTTPS Response
```
**プロキシ** は元のクライアントリクエストを受け取り、**アプリケーションサーバー** に渡す前に特別な「転送」ヘッダー(`X-Forwarded-*`)を追加します。
これらのヘッダーは、通常は失われる元のリクエストの情報を保持します:
* **X-Forwarded-For**: 元のクライアントの IP アドレス
* **X-Forwarded-Proto**: 元のプロトコル(`https`
* **X-Forwarded-Host**: 元のホスト(`mysuperapp.com`
**FastAPI CLI** を `--forwarded-allow-ips` で設定すると、これらのヘッダーを信頼して使用し、たとえばリダイレクトで正しい URL を生成します。
## パスプレフィックスを削除するプロキシ { #proxy-with-a-stripped-path-prefix }
アプリケーションにパスプレフィックスを付与するプロキシを使う場合があります。
そのような場合は `root_path` でアプリケーションを設定できます。
`root_path`FastAPI が Starlette を通して基づいているASGI 仕様で提供されている仕組みです。
`root_path` はこの種のケースを扱うために使われます。
これはサブアプリケーションをマウントする際にも内部的に使用されます。
ここでいう「パスプレフィックスを削除するプロキシ」とは、コード上では `/app` というパスを宣言していても、その上にプロキシ層を追加して **FastAPI** アプリケーションを `/api/v1` のようなパスの下に配置することを指します。
この場合、元のパス `/app` は実際には `/api/v1/app` で提供されます。
すべてのコードは `/app` だけを前提に書かれているにもかかわらず、です。
{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *}
そしてプロキシは、アプリサーバー(おそらく FastAPI CLI 経由の Uvicornに転送する前に、その場で **パスプレフィックス** を**「削除」**し、アプリケーション側には自分が `/app` で提供されているように見せかけます。これにより、コードのすべてを `/api/v1` のプレフィックス付きに書き換える必要がありません。
ここまでは通常どおりに動作します。
しかし、統合ドキュメント UIフロントエンドを開くと、OpenAPI スキーマを `/api/v1/openapi.json` ではなく `/openapi.json` から取得しようとします。
そのため、フロントエンド(ブラウザで動作)は `/openapi.json` にアクセスしようとして、OpenAPI スキーマを取得できません。
このアプリには `/api/v1` のパスプレフィックスを付与するプロキシがあるため、フロントエンドは `/api/v1/openapi.json` から取得する必要があります。
```mermaid
graph LR
browser("Browser")
proxy["Proxy on http://0.0.0.0:9999/api/v1/app"]
server["Server on http://127.0.0.1:8000/app"]
browser --> proxy
proxy --> server
```
/// tip | 豆知識
IP `0.0.0.0` は、そのマシン/サーバーで利用可能なすべての IP で待ち受けることを意味する表現として一般的に使われます。
///
ドキュメント UI では、この API の `server` が(プロキシの背後で)`/api/v1` にあることを宣言する OpenAPI スキーマも必要です。例えば:
```JSON hl_lines="4-8"
{
"openapi": "3.1.0",
// ほかの項目
"servers": [
{
"url": "/api/v1"
}
],
"paths": {
// ほかの項目
}
}
```
この例では「Proxy」は **Traefik** のようなもの、サーバーは **Uvicorn** と FastAPI CLI で FastAPI アプリケーションを実行しているものを想定しています。
### `root_path` の指定 { #providing-the-root-path }
これを実現するには、次のようにコマンドラインオプション `--root-path` を使用します:
<div class="termy">
```console
$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
Hypercorn を使う場合も、同様に `--root-path` オプションがあります。
/// note | 技術詳細
このユースケース向けに、ASGI 仕様は `root_path` を定義しています。
そして `--root-path` コマンドラインオプションは、その `root_path` を提供します。
///
### 現在の `root_path` の確認 { #checking-the-current-root-path }
各リクエストでアプリケーションが使用している現在の `root_path` は取得できます。これはASGI 仕様の一部である)`scope` 辞書に含まれます。
ここではデモのため、メッセージに含めています。
{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *}
そのうえで、次のように Uvicorn を起動すると:
<div class="termy">
```console
$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
レスポンスは次のようになります:
```JSON
{
"message": "Hello World",
"root_path": "/api/v1"
}
```
### FastAPI アプリでの `root_path` 設定 { #setting-the-root-path-in-the-fastapi-app }
あるいは、`--root-path` のようなコマンドラインオプションを渡せない場合は、FastAPI アプリ作成時にパラメータ `root_path` を設定できます:
{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *}
`FastAPI``root_path` を渡すのは、Uvicorn や Hypercorn にコマンドラインオプション `--root-path` を渡すのと同等です。
### `root_path` について { #about-root-path }
サーバーUvicornは、その `root_path` をアプリに渡す以外の用途では使用しない点に注意してください。
しかし、ブラウザで <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> にアクセスすると、通常どおりのレスポンスが表示されます:
```JSON
{
"message": "Hello World",
"root_path": "/api/v1"
}
```
つまり、`http://127.0.0.1:8000/api/v1/app` でアクセスされることは想定していません。
Uvicorn は、プロキシが `http://127.0.0.1:8000/app` にアクセスしてくることを想定しており、その上に追加の `/api/v1` プレフィックスを付けるのはプロキシの責務です。
## パスプレフィックスを削除するプロキシについて { #about-proxies-with-a-stripped-path-prefix }
パスプレフィックスを削除するプロキシは、設定方法の一例にすぎない点に注意してください。
多くの場合、プロキシはパスプレフィックスを削除しない設定が既定でしょう。
そのような場合(パスプレフィックスを削除しない場合)は、プロキシは `https://myawesomeapp.com` のようなアドレスで待ち受け、ブラウザが `https://myawesomeapp.com/api/v1/app` にアクセスし、サーバー(例: Uvicorn`http://127.0.0.1:8000` で待ち受けているなら、プロキシ(プレフィックスを削除しない)は同じパス `http://127.0.0.1:8000/api/v1/app` で Uvicorn にアクセスします。
## Traefik を使ったローカル検証 { #testing-locally-with-traefik }
<a href="https://docs.traefik.io/" class="external-link" target="_blank">Traefik</a> を使えば、パスプレフィックスを削除する構成をローカルで簡単に試せます。
<a href="https://github.com/containous/traefik/releases" class="external-link" target="_blank">Traefik をダウンロード</a> してください。単一バイナリなので、圧縮ファイルを展開して端末から直接実行できます。
次の内容で `traefik.toml` というファイルを作成します:
```TOML hl_lines="3"
[entryPoints]
[entryPoints.http]
address = ":9999"
[providers]
[providers.file]
filename = "routes.toml"
```
これは Traefik にポート 9999 で待ち受け、別のファイル `routes.toml` を使用するよう指示します。
/// tip | 豆知識
標準の HTTP ポート 80 ではなく 9999 を使うのは、管理者(`sudo`)権限で実行する必要をなくすためです。
///
次に、その `routes.toml` ファイルを作成します:
```TOML hl_lines="5 12 20"
[http]
[http.middlewares]
[http.middlewares.api-stripprefix.stripPrefix]
prefixes = ["/api/v1"]
[http.routers]
[http.routers.app-http]
entryPoints = ["http"]
service = "app"
rule = "PathPrefix(`/api/v1`)"
middlewares = ["api-stripprefix"]
[http.services]
[http.services.app]
[http.services.app.loadBalancer]
[[http.services.app.loadBalancer.servers]]
url = "http://127.0.0.1:8000"
```
このファイルは Traefik に `/api/v1` のパスプレフィックスを使うよう設定します。
そして Traefik は、`http://127.0.0.1:8000` で動作している Uvicorn へリクエストを転送します。
では Traefik を起動します:
<div class="termy">
```console
$ ./traefik --configFile=traefik.toml
INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml
```
</div>
次に、`--root-path` オプションを指定してアプリを起動します:
<div class="termy">
```console
$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
### レスポンスの確認 { #check-the-responses }
ここで、Uvicorn のポートの URL <a href="http://127.0.0.1:8000/app" class="external-link" target="_blank">http://127.0.0.1:8000/app</a> にアクセスすると、通常どおりのレスポンスが表示されます:
```JSON
{
"message": "Hello World",
"root_path": "/api/v1"
}
```
/// tip | 豆知識
`http://127.0.0.1:8000/app` にアクセスしているにもかかわらず、オプション `--root-path` から取得した `root_path``/api/v1` と表示されている点に注目してください。
///
次に、Traefik のポートでプレフィックス付きの URL <a href="http://127.0.0.1:9999/api/v1/app" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/app</a> を開きます。
同じレスポンスが得られます:
```JSON
{
"message": "Hello World",
"root_path": "/api/v1"
}
```
ただし今回は、プロキシが付与したプレフィックス `/api/v1` の付いた URL です。
もちろん、ここでの想定は全員がプロキシ経由でアプリにアクセスすることです。したがって、パスプレフィックス `/api/v1` のある版が「正しい」アクセス方法になります。
一方、プレフィックスのない版(`http://127.0.0.1:8000/app`。Uvicorn が直接提供は、_プロキシ_Traefik専用の接続先になります。
これにより、プロキシTraefikがパスプレフィックスをどのように用い、サーバーUvicorn`--root-path``root_path` をどのように利用するかが分かります。
### ドキュメント UI の確認 { #check-the-docs-ui }
ここがポイントです。✨
「公式な」アクセス方法は、定義したパスプレフィックス付きのプロキシ経由です。したがって想定どおり、プレフィックスなしの URL で Uvicorn が直接提供するドキュメント UI にアクセスすると動作しません。プロキシ経由でアクセスされることを前提としているためです。
<a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> を確認してください:
<img src="/img/tutorial/behind-a-proxy/image01.png">
しかし、プロキシ(ポート `9999`を使った「公式」URL `/api/v1/docs` でドキュメント UI にアクセスすると、正しく動作します!🎉
<a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a> を確認してください:
<img src="/img/tutorial/behind-a-proxy/image02.png">
ねらいどおりです。✔️
これは、FastAPI が `root_path` を使って、OpenAPI の既定の `server``root_path` の URL で生成するためです。
## 追加のサーバー { #additional-servers }
/// warning | 注意
これは高度なユースケースです。読み飛ばしても構いません。
///
既定では、**FastAPI** は OpenAPI スキーマ内に `root_path` の URL を持つ `server` を作成します。
しかし、ステージングと本番の両方と同じドキュメント UI で対話させたい場合など、別の `servers` を指定することもできます。
カスタムの `servers` リストを渡していて、かつ `root_path`API がプロキシの背後にあるため)が設定されている場合、**FastAPI** はこの `root_path` を用いた「server」をリストの先頭に挿入します。
例えば:
{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *}
次のような OpenAPI スキーマが生成されます:
```JSON hl_lines="5-7"
{
"openapi": "3.1.0",
// ほかの項目
"servers": [
{
"url": "/api/v1"
},
{
"url": "https://stag.example.com",
"description": "Staging environment"
},
{
"url": "https://prod.example.com",
"description": "Production environment"
}
],
"paths": {
// ほかの項目
}
}
```
/// tip | 豆知識
`root_path` から取得した `url``/api/v1` を持つ server が自動生成されている点に注目してください。
///
ドキュメント UI<a href="http://127.0.0.1:9999/api/v1/docs" class="external-link" target="_blank">http://127.0.0.1:9999/api/v1/docs</a>)では次のように表示されます:
<img src="/img/tutorial/behind-a-proxy/image03.png">
/// tip | 豆知識
ドキュメント UI は、選択した server と対話します。
///
/// note | 技術詳細
OpenAPI 仕様の `servers` プロパティは任意です。
`servers` パラメータを指定せず、かつ `root_path``/` の場合、生成される OpenAPI スキーマからは `servers` プロパティが既定で完全に省略されます。これは、`url` が `/` の server が 1 つあるのと同等です。
///
### `root_path` 由来の自動 server を無効化 { #disable-automatic-server-from-root-path }
`root_path` を用いた自動的な server を **FastAPI** に含めてほしくない場合は、パラメータ `root_path_in_servers=False` を使用します:
{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *}
すると、OpenAPI スキーマには含まれません。
## サブアプリケーションのマウント { #mounting-a-sub-application }
`root_path` を伴うプロキシを使用しつつサブアプリケーションをマウントする必要がある場合でも([サブアプリケーション - マウント](sub-applications.md){.internal-link target=_blank} 参照)、通常どおりに行えます。
FastAPI は内部で `root_path` を適切に扱うため、そのまま動作します。✨

View File

@ -30,7 +30,7 @@
しかし、返そうとしているコンテンツが **JSONでシリアライズ可能**であることが確実なら、それを直接レスポンスクラスに渡して、FastAPIがレスポンスクラスへ渡す前に返却コンテンツを `jsonable_encoder` に通すことで発生する追加のオーバーヘッドを回避できます。
{* ../../docs_src/custom_response/tutorial001b_py39.py hl[2,7] *}
{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *}
/// info | 情報
@ -55,7 +55,7 @@
* `HTMLResponse` をインポートする。
* *path operation デコレータ* のパラメータ `response_class``HTMLResponse` を渡す。
{* ../../docs_src/custom_response/tutorial002_py39.py hl[2,7] *}
{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *}
/// info | 情報
@ -73,7 +73,7 @@
上記と同じ例において、 `HTMLResponse` を返すと、このようになります:
{* ../../docs_src/custom_response/tutorial003_py39.py hl[2,7,19] *}
{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *}
/// warning | 注意
@ -97,7 +97,7 @@
例えば、このようになります:
{* ../../docs_src/custom_response/tutorial004_py39.py hl[7,21,23] *}
{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *}
この例では、関数 `generate_html_response()` は、`str` のHTMLを返すのではなく、`Response` を生成して返しています。
@ -136,7 +136,7 @@
FastAPI実際にはStarletteは自動的にContent-Lengthヘッダーを含みます。また、`media_type` に基づいたContent-Typeヘッダーを含み、テキストタイプのためにcharsetを追加します。
{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
### `HTMLResponse` { #htmlresponse }
@ -146,7 +146,7 @@ FastAPI実際にはStarletteは自動的にContent-Lengthヘッダーを
テキストやバイトを受け取り、プレーンテキストのレスポンスを返します。
{* ../../docs_src/custom_response/tutorial005_py39.py hl[2,7,9] *}
{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *}
### `JSONResponse` { #jsonresponse }
@ -180,7 +180,7 @@ FastAPI実際にはStarletteは自動的にContent-Lengthヘッダーを
///
{* ../../docs_src/custom_response/tutorial001_py39.py hl[2,7] *}
{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *}
/// tip | 豆知識
@ -194,13 +194,13 @@ HTTPリダイレクトを返します。デフォルトでは307ステータス
`RedirectResponse` を直接返せます:
{* ../../docs_src/custom_response/tutorial006_py39.py hl[2,9] *}
{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *}
---
または、`response_class` パラメータで使用できます:
{* ../../docs_src/custom_response/tutorial006b_py39.py hl[2,7,9] *}
{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *}
その場合、*path operation*関数からURLを直接返せます。
@ -210,13 +210,13 @@ HTTPリダイレクトを返します。デフォルトでは307ステータス
また、`status_code` パラメータを `response_class` パラメータと組み合わせて使うこともできます:
{* ../../docs_src/custom_response/tutorial006c_py39.py hl[2,7,9] *}
{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *}
### `StreamingResponse` { #streamingresponse }
非同期ジェネレータ、または通常のジェネレータ/イテレータを受け取り、レスポンスボディをストリームします。
{* ../../docs_src/custom_response/tutorial007_py39.py hl[2,14] *}
{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *}
#### ファイルライクオブジェクトで `StreamingResponse` を使う { #using-streamingresponse-with-file-like-objects }
@ -226,7 +226,7 @@ HTTPリダイレクトを返します。デフォルトでは307ステータス
これにはクラウドストレージとの連携、映像処理など、多くのライブラリが含まれます。
{* ../../docs_src/custom_response/tutorial008_py39.py hl[2,10:12,14] *}
{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *}
1. これはジェネレータ関数です。内部に `yield` 文を含むため「ジェネレータ関数」です。
2. `with` ブロックを使うことで、ジェネレータ関数が終わった後つまりレスポンスの送信が完了した後にfile-likeオブジェクトが確実にクローズされるようにします。
@ -255,11 +255,11 @@ HTTPリダイレクトを返します。デフォルトでは307ステータス
ファイルレスポンスには、適切な `Content-Length`、`Last-Modified`、`ETag` ヘッダーが含まれます。
{* ../../docs_src/custom_response/tutorial009_py39.py hl[2,10] *}
{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *}
`response_class` パラメータを使うこともできます:
{* ../../docs_src/custom_response/tutorial009b_py39.py hl[2,8,10] *}
{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *}
この場合、*path operation*関数からファイルパスを直接返せます。
@ -273,7 +273,7 @@ HTTPリダイレクトを返します。デフォルトでは307ステータス
`CustomORJSONResponse` を作れます。主に必要なのは、コンテンツを `bytes` として返す `Response.render(content)` メソッドを作ることです:
{* ../../docs_src/custom_response/tutorial009c_py39.py hl[9:14,17] *}
{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *}
これまでは次のように返していたものが:
@ -299,7 +299,7 @@ HTTPリダイレクトを返します。デフォルトでは307ステータス
以下の例では、**FastAPI** はすべての*path operation*で、`JSONResponse` の代わりに `ORJSONResponse` をデフォルトとして使います。
{* ../../docs_src/custom_response/tutorial010_py39.py hl[2,4] *}
{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *}
/// tip | 豆知識

View File

@ -0,0 +1,95 @@
# Dataclasses の使用 { #using-dataclasses }
FastAPI は **Pydantic** の上に構築されており、これまでにリクエストやレスポンスを宣言するために Pydantic モデルを使う方法を紹介してきました。
しかし FastAPI は、同様の方法で <a href="https://docs.python.org/3/library/dataclasses.html" class="external-link" target="_blank">`dataclasses`</a> もサポートします:
{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *}
これは **Pydantic** によって引き続きサポートされています。Pydantic には <a href="https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel" class="external-link" target="_blank">`dataclasses` の内部サポート</a> があるためです。
そのため、上記のように明示的に Pydantic を使っていないコードでも、FastAPI は標準の dataclass を Pydantic 独自の dataclass に変換するために Pydantic を使用しています。
そして当然ながら、次の点も同様にサポートされます:
- データ検証
- データのシリアライズ
- データのドキュメント化 など
これは Pydantic モデルの場合と同じように動作します。内部的にも同様に Pydantic を使って実現されています。
/// info | 情報
dataclasses は、Pydantic モデルができることをすべては行えない点に留意してください。
そのため、Pydantic モデルを使う必要がある場合もあります。
しかし既存の dataclass が多数あるなら、FastAPI で Web API を構築する際にそれらを活用するちょっとしたテクニックになります。🤓
///
## `response_model` での dataclasses { #dataclasses-in-response-model }
`response_model` パラメータでも `dataclasses` を使用できます:
{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *}
dataclass は自動的に Pydantic の dataclass に変換されます。
このため、そのスキーマは API ドキュメントの UI に表示されます:
<img src="/img/tutorial/dataclasses/image01.png">
## ネストしたデータ構造での dataclasses { #dataclasses-in-nested-data-structures }
`dataclasses` を他の型注釈と組み合わせて、ネストしたデータ構造を作成できます。
場合によっては、自動生成された API ドキュメントでエラーが発生するなどの理由で、Pydantic 版の `dataclasses` を使う必要があるかもしれません。
その場合は、標準の `dataclasses``pydantic.dataclasses` に置き換えるだけで済みます。これはドロップイン置換です:
{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *}
1. 依然として標準の `dataclasses` から `field` をインポートします。
2. `pydantic.dataclasses``dataclasses` のドロップイン置換です。
3. `Author` dataclass は `Item` dataclass のリストを含みます。
4. `Author` dataclass を `response_model` パラメータとして使用しています。
5. リクエストボディとしての dataclass と併せて、他の標準の型注釈を使用できます。
この例では、`Item` dataclass のリストです。
6. ここでは、dataclass のリストである `items` を含む辞書を返しています。
FastAPI はデータを JSON に <dfn title="送信可能な形式にデータを変換すること">シリアライズ</dfn> できます。
7. ここでは `response_model``Author` dataclass のリストという型注釈を使用しています。
このように、`dataclasses` は標準の型注釈と組み合わせられます。
8. この *path operation 関数* は、`async def` ではなく通常の `def` を使用しています。
いつもどおり、FastAPI では必要に応じて `def``async def` を組み合わせられます。
どちらをいつ使うかの復習が必要な場合は、[`async` と `await`](../async.md#in-a-hurry){.internal-link target=_blank} に関するドキュメントの _"In a hurry?"_ セクションを参照してください。
9. この *path operation 関数*可能ではありますがdataclass 自体は返さず、内部データを持つ辞書のリストを返しています。
FastAPI は dataclass を含む `response_model` パラメータを使ってレスポンスを変換します。
`dataclasses` は他の型注釈と多様な組み合わせが可能で、複雑なデータ構造を構成できます。
上記のコード内コメントのヒントを参照して、より具体的な詳細を確認してください。
## さらに学ぶ { #learn-more }
`dataclasses` を他の Pydantic モデルと組み合わせたり、継承したり、自分のモデルに含めたりもできます。
詳しくは、<a href="https://docs.pydantic.dev/latest/concepts/dataclasses/" class="external-link" target="_blank">dataclasses に関する Pydantic ドキュメント</a> を参照してください。
## バージョン { #version }
これは FastAPI バージョン `0.67.0` 以降で利用可能です。🔖

View File

@ -0,0 +1,165 @@
# Lifespan イベント { #lifespan-events }
アプリケーションが起動する前に一度だけ実行すべきロジック(コード)を定義できます。これは、アプリケーションがリクエストを受け取り始める前に、そのコードが一度だけ実行される、という意味です。
同様に、アプリケーションがシャットダウンするときに実行すべきロジック(コード)も定義できます。この場合、そのコードは、(多くのリクエストを処理した)後に一度だけ実行されます。
このコードは、アプリケーションがリクエストの受け付けを「開始」する前、そして処理を「終了」した直後に実行されるため、アプリケーションの全体の「Lifespan」この「lifespan」という言葉はすぐ後で重要になります 😉)をカバーします。
これは、アプリ全体で使用し、リクエスト間で「共有」し、かつ後で「クリーンアップ」する必要があるような「リソース」をセットアップするのにとても便利です。たとえば、データベース接続プールや、共有の機械学習モデルの読み込みなどです。
## ユースケース { #use-case }
まずはユースケースの例から始めて、これをどのように解決するかを見ていきます。
リクエストを処理するために使用したい「機械学習モデル」がいくつかあると想像してください。🤖
同じモデルをリクエスト間で共有するので、リクエストごとやユーザーごとに別々のモデルを使うわけではありません。
モデルの読み込みにはディスクから大量のデータを読む必要があり、かなり時間がかかるかもしれません。したがって、リクエストごとに読み込みたくはありません。
モジュール/ファイルのトップレベルで読み込むこともできますが、その場合は、たとえ簡単な自動テストを実行するだけでも「モデルを読み込む」ことになり、そのモデルの読み込みを待つ必要があるため、独立したコード部分を走らせるだけのテストでも「遅く」なってしまいます。
これを解決しましょう。リクエストを処理する前にモデルを読み込みますが、コードがロードされている最中ではなく、アプリケーションがリクエストの受け付けを開始する直前だけにします。
## Lifespan { #lifespan }
この「起動時」と「シャットダウン時」のロジックは、`FastAPI` アプリの `lifespan` パラメータと「コンテキストマネージャ」(これが何かはすぐに示します)を使って定義できます。
まずは例を見てから、詳細を説明します。
次のように、`yield` を使う非同期関数 `lifespan()` を作成します:
{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *}
ここでは、`yield` の前で機械学習モデルの辞書に(ダミーの)モデル関数を入れることで、高コストな「起動時」のモデル読み込みをシミュレーションしています。このコードは、アプリケーションがリクエストを「受け付け始める前」に、すなわち起動時に実行されます。
そして `yield` の直後でモデルをアンロードします。このコードは、アプリケーションがリクエスト処理を「終了」した後、シャットダウン直前に実行されます。たとえばメモリや GPU のようなリソースを解放できます。
/// tip | 豆知識
`shutdown` は、アプリケーションを「停止」するときに発生します。
新しいバージョンを開始する必要があるか、単に実行をやめたくなったのかもしれません。🤷
///
### Lifespan 関数 { #lifespan-function }
まず注目すべきは、`yield` を使う非同期関数を定義していることです。これは「yield を使う依存関係Dependencies」にとてもよく似ています。
{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *}
`yield` の前の前半は、アプリケーションが開始される「前」に実行されます。
`yield` の後半は、アプリケーションの処理が「終了」した「後」に実行されます。
### 非同期コンテキストマネージャ { #async-context-manager }
この関数には `@asynccontextmanager` がデコレートされています。
これにより、この関数は「非同期コンテキストマネージャ」になります。
{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *}
Python の「コンテキストマネージャ」は、`with` 文で使えるものです。たとえば、`open()` はコンテキストマネージャとして使えます:
```Python
with open("file.txt") as file:
file.read()
```
最近の Python には「非同期コンテキストマネージャ」もあります。`async with` で使います:
```Python
async with lifespan(app):
await do_stuff()
```
このようにコンテキストマネージャ(または非同期コンテキストマネージャ)を作ると、`with` ブロックに入る前に `yield` より前のコードが実行され、`with` ブロックを出た後に `yield` より後ろのコードが実行されます。
上のコード例では直接それを使ってはいませんが、FastAPI に渡して内部で使ってもらいます。
`FastAPI` アプリの `lifespan` パラメータは「非同期コンテキストマネージャ」を受け取るので、新しく作った `lifespan` 非同期コンテキストマネージャを渡せます。
{* ../../docs_src/events/tutorial003_py310.py hl[22] *}
## 代替のイベント(非推奨) { #alternative-events-deprecated }
/// warning | 注意
推奨される方法は、上で説明したとおり `FastAPI` アプリの `lifespan` パラメータを使って「起動」と「シャットダウン」を扱うことです。`lifespan` パラメータを指定すると、`startup` と `shutdown` のイベントハンドラは呼び出されなくなります。`lifespan` かイベントか、どちらか一方であり、両方同時ではありません。
この節は読み飛ばしてもかまいません。
///
起動時とシャットダウン時に実行されるロジックを定義する別の方法もあります。
アプリケーションが起動する前、またはシャットダウンするときに実行する必要があるイベントハンドラ(関数)を定義できます。
これらの関数は `async def` でも、通常の `def` でも構いません。
### `startup` イベント { #startup-event }
アプリケーションが開始される前に実行すべき関数を追加するには、イベント `"startup"` で宣言します:
{* ../../docs_src/events/tutorial001_py310.py hl[8] *}
この場合、`startup` のイベントハンドラ関数は items の「データベース」(単なる `dict`)をいくつかの値で初期化します。
イベントハンドラ関数は複数追加できます。
すべての `startup` イベントハンドラが完了するまで、アプリケーションはリクエストの受け付けを開始しません。
### `shutdown` イベント { #shutdown-event }
アプリケーションがシャットダウンするときに実行すべき関数を追加するには、イベント `"shutdown"` で宣言します:
{* ../../docs_src/events/tutorial002_py310.py hl[6] *}
ここでは、`shutdown` のイベントハンドラ関数が、テキスト行 `"Application shutdown"` をファイル `log.txt` に書き込みます。
/// info | 情報
`open()` 関数の `mode="a"` は「追加」appendを意味します。つまり、そのファイルに既にある内容を上書きせず、行が後ろに追記されます。
///
/// tip | 豆知識
この例では、ファイルを扱う標準の Python 関数 `open()` を使っています。
そのため、ディスクへの書き込みを「待つ」必要がある I/O入力/出力)が関わります。
しかし `open()` 自体は `async``await` を使いません。
したがって、イベントハンドラ関数は `async def` ではなく通常の `def` で宣言しています。
///
### `startup``shutdown` をまとめて { #startup-and-shutdown-together }
起動時とシャットダウン時のロジックは関連していることが多いです。何かを開始してから終了したい、リソースを獲得してから解放したい、などです.
共有するロジックや変数のない別々の関数でそれを行うのは難しく、グローバル変数などに値を保存する必要が出てきます。
そのため、現在は上で説明したとおり `lifespan` を使うことが推奨されています。
## 技術詳細 { #technical-details }
技術が気になる方への細かな詳細です。🤓
内部的には、ASGI の技術仕様において、これは <a href="https://asgi.readthedocs.io/en/latest/specs/lifespan.html" class="external-link" target="_blank">Lifespan プロトコル</a> の一部であり、`startup` と `shutdown` というイベントが定義されています。
/// info | 情報
Starlette の `lifespan` ハンドラについては、<a href="https://www.starlette.dev/lifespan/" class="external-link" target="_blank">Starlette の Lifespan ドキュメント</a>で詳しく読むことができます。
コードの他の領域で使える lifespan の状態をどのように扱うかも含まれています。
///
## サブアプリケーション { #sub-applications }
🚨 これらの lifespan イベントstartup と shutdownはメインのアプリケーションに対してのみ実行され、[サブアプリケーション - マウント](sub-applications.md){.internal-link target=_blank} には実行されないことに注意してください。

View File

@ -0,0 +1,208 @@
# SDK の生成 { #generating-sdks }
**FastAPI** は **OpenAPI** 仕様に基づいているため、その API は多くのツールが理解できる標準形式で記述できます。
これにより、最新の**ドキュメント**、複数言語のクライアントライブラリ(<abbr title="Software Development Kits - ソフトウェア開発キット">**SDKs**</abbr>)、そしてコードと同期し続ける**テスト**や**自動化ワークフロー**を容易に生成できます。
本ガイドでは、FastAPI バックエンド向けの **TypeScript SDK** を生成する方法を説明します。
## オープソースの SDK ジェネレータ { #open-source-sdk-generators }
多用途な選択肢として <a href="https://openapi-generator.tech/" class="external-link" target="_blank">OpenAPI Generator</a> があります。これは**多数のプログラミング言語**をサポートし、OpenAPI 仕様から SDK を生成できます。
**TypeScript クライアント**向けには、<a href="https://heyapi.dev/" class="external-link" target="_blank">Hey API</a> が目的特化のソリューションで、TypeScript エコシステムに最適化された体験を提供します。
他の SDK ジェネレータは <a href="https://openapi.tools/#sdk" class="external-link" target="_blank">OpenAPI.Tools</a> でも見つけられます。
/// tip | 豆知識
FastAPI は自動的に **OpenAPI 3.1** の仕様を生成します。したがって、使用するツールはこのバージョンをサポートしている必要があります。
///
## FastAPI スポンサーによる SDK ジェネレータ { #sdk-generators-from-fastapi-sponsors }
このセクションでは、FastAPI をスポンサーしている企業による、**ベンチャー支援**および**企業支援**のソリューションを紹介します。これらの製品は、高品質な生成 SDK に加えて、**追加機能**や**統合**を提供します。
✨ [**FastAPI をスポンサーする**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨ ことで、これらの企業はフレームワークとその**エコシステム**の健全性と**持続可能性**を支援しています。
この支援は、FastAPI の**コミュニティ**(皆さん)への強いコミットメントの表明でもあり、**優れたサービス**の提供だけでなく、堅牢で発展するフレームワーク FastAPI を支える姿勢を示しています。🙇
例えば、次のようなものがあります:
* <a href="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship" class="external-link" target="_blank">Speakeasy</a>
* <a href="https://www.stainless.com/?utm_source=fastapi&utm_medium=referral" class="external-link" target="_blank">Stainless</a>
* <a href="https://developers.liblab.com/tutorials/sdk-for-fastapi?utm_source=fastapi" class="external-link" target="_blank">liblab</a>
これらのソリューションの中にはオープンソースや無料枠を提供するものもあり、金銭的コミットメントなしで試すことができます。他の商用 SDK ジェネレータも存在し、オンラインで見つけられます。🤓
## TypeScript SDK を作成する { #create-a-typescript-sdk }
まずは簡単な FastAPI アプリから始めます:
{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *}
ここで、*path operation* はリクエストとレスポンスのペイロードに使用するモデルを定義しており、`Item` と `ResponseMessage` を使っています。
### API ドキュメント { #api-docs }
`/docs` に移動すると、リクエストで送信・レスポンスで受信するデータの**スキーマ**が表示されます:
<img src="/img/tutorial/generate-clients/image01.png">
これらのスキーマは、アプリ内でモデルとして宣言されているため表示されます。
その情報はアプリの **OpenAPI スキーマ**に含まれ、API ドキュメントに表示されます。
OpenAPI に含まれるこれらのモデル情報を使って、**クライアントコードを生成**できます。
### Hey API { #hey-api }
モデルを備えた FastAPI アプリがあれば、Hey API で TypeScript クライアントを生成できます。最も手早い方法は npx を使うことです。
```sh
npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client
```
これで TypeScript SDK が `./src/client` に生成されます。
<a href="https://heyapi.dev/openapi-ts/get-started" class="external-link" target="_blank">`@hey-api/openapi-ts` のインストール方法</a>や、<a href="https://heyapi.dev/openapi-ts/output" class="external-link" target="_blank">生成物の詳細</a>は公式サイトを参照してください。
### SDK の利用 { #using-the-sdk }
これでクライアントコードを import して利用できます。例えば次のようになり、メソッドに対して補完が効きます:
<img src="/img/tutorial/generate-clients/image02.png">
送信するペイロードにも補完が適用されます:
<img src="/img/tutorial/generate-clients/image03.png">
/// tip | 豆知識
FastAPI アプリの `Item` モデルで定義した `name``price` に補完が効いている点に注目してください。
///
送信データに対するインラインエラーも表示されます:
<img src="/img/tutorial/generate-clients/image04.png">
レスポンスオブジェクトにも補完があります:
<img src="/img/tutorial/generate-clients/image05.png">
## タグ付きの FastAPI アプリ { #fastapi-app-with-tags }
実運用ではアプリは大きくなり、*path operation* のグループ分けにタグを使うことが多いでしょう。
例えば **items** 用と **users** 用のセクションがあり、タグで分けられます:
{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *}
### タグ付き TypeScript クライアントの生成 { #generate-a-typescript-client-with-tags }
タグを用いた FastAPI アプリからクライアントを生成すると、通常クライアント側のコードもタグごとに分割されます。
これにより、クライアントコードも正しく整理・グルーピングされます:
<img src="/img/tutorial/generate-clients/image06.png">
この例では次のようになります:
* `ItemsService`
* `UsersService`
### クライアントのメソッド名 { #client-method-names }
現状では、生成されるメソッド名(`createItemItemsPost` など)はあまりきれいではありません:
```TypeScript
ItemsService.createItemItemsPost({name: "Plumbus", price: 5})
```
これは、クライアントジェネレータが各 *path operation* の OpenAPI 内部の **operation ID** を用いるためです。
OpenAPI では operation ID は全ての *path operation* を通して一意である必要があります。そのため FastAPI は**関数名**、**パス**、**HTTP メソッド/オペレーション**を組み合わせて operation ID を生成し、一意性を保証します。
次にこれを改善する方法を示します。🤓
## カスタム operation ID とより良いメソッド名 { #custom-operation-ids-and-better-method-names }
operation ID の**生成方法**を**変更**して簡潔にし、クライアント側の**メソッド名をシンプル**にできます。
この場合でも各 operation ID が**一意**であることは別の方法で保証する必要があります。
例えば、各 *path operation* にタグを付け、**タグ**と *path operation* の**名前**(関数名)から operation ID を生成できます。
### 一意 ID 生成関数のカスタマイズ { #custom-generate-unique-id-function }
FastAPI は各 *path operation* に**一意 ID**を用いており、これは **operation ID** のほか、必要に応じてリクエストやレスポンスのカスタムモデル名にも使われます。
この関数はカスタマイズ可能です。`APIRoute` を受け取り、文字列を返します。
例えばここでは、最初のタグ(通常は 1 つ)と *path operation* 名(関数名)を使います。
そのカスタム関数を **FastAPI**`generate_unique_id_function` パラメータに渡します:
{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *}
### カスタム operation ID で TypeScript クライアントを生成 { #generate-a-typescript-client-with-custom-operation-ids }
この状態でクライアントを再生成すると、メソッド名が改善されています:
<img src="/img/tutorial/generate-clients/image07.png">
ご覧のとおり、メソッド名はタグ名と関数名のみになり、URL パスや HTTP オペレーションの情報は含まれません。
### クライアント生成向けの OpenAPI 仕様の前処理 { #preprocess-the-openapi-specification-for-the-client-generator }
それでも生成コードには**重複情報**が残っています。
`ItemsService`(タグ由来)から items 関連であることはすでに分かるのに、メソッド名にもタグ名が前置されています。😕
OpenAPI 全体としては operation ID の**一意性**のために、このプレフィックスを維持したい場合があるでしょう。
しかし生成クライアント用には、クライアントを生成する直前に OpenAPI の operation ID を**加工**して、メソッド名をより**見やすく**、**クリーン**にできます。
OpenAPI の JSON を `openapi.json` として保存し、次のようなスクリプトで**そのタグのプレフィックスを除去**できます:
{* ../../docs_src/generate_clients/tutorial004_py310.py *}
//// tab | Node.js
```Javascript
{!> ../../docs_src/generate_clients/tutorial004.js!}
```
////
これにより operation ID は `items-get_items` のような形から単なる `get_items` に置き換わり、クライアントジェネレータはより簡潔なメソッド名を生成できます。
### 前処理済み OpenAPI から TypeScript クライアントを生成 { #generate-a-typescript-client-with-the-preprocessed-openapi }
生成元が `openapi.json` になったので、入力の場所を更新します:
```sh
npx @hey-api/openapi-ts -i ./openapi.json -o src/client
```
新しいクライアントを生成すると、**クリーンなメソッド名**になり、**補完**や**インラインエラー**などもそのまま利用できます:
<img src="/img/tutorial/generate-clients/image08.png">
## 利点 { #benefits }
自動生成されたクライアントを使うと、次のような対象で**補完**が得られます:
* メソッド
* 本体のリクエストペイロード、クエリパラメータ等
* レスポンスのペイロード
また、あらゆる箇所で**インラインエラー**も得られます。
バックエンドコードを更新してフロントエンドを**再生成**すれば、新しい *path operation* はメソッドとして追加され、古いものは削除され、その他の変更も生成コードに反映されます。🤓
つまり、変更があれば自動的にクライアントコードに**反映**されます。クライアントを**ビルド**すれば、使用データに**不整合**があればエラーになります。
その結果、多くのエラーを開発の初期段階で**早期発見**でき、本番で最終ユーザーに不具合が現れてから原因をデバッグする必要がなくなります。✨

View File

@ -0,0 +1,97 @@
# 高度なミドルウェア { #advanced-middleware }
メインのチュートリアルでは、アプリケーションに[カスタムミドルウェア](../tutorial/middleware.md){.internal-link target=_blank}を追加する方法を学びました。
そして、[`CORSMiddleware` を使った CORS の扱い方](../tutorial/cors.md){.internal-link target=_blank}も学びました。
このセクションでは、その他のミドルウェアの使い方を見ていきます。
## ASGI ミドルウェアの追加 { #adding-asgi-middlewares }
**FastAPI** は Starlette を基盤としており、<abbr title="Asynchronous Server Gateway Interface - 非同期サーバーゲートウェイインターフェース">ASGI</abbr> 仕様を実装しているため、任意の ASGI ミドルウェアを利用できます。
ミドルウェアは ASGI 仕様に従っていれば、FastAPI や Starlette 専用に作られていなくても動作します。
一般に、ASGI ミドルウェアは最初の引数として ASGI アプリを受け取るクラスです。
そのため、サードパーティの ASGI ミドルウェアのドキュメントでは、おそらく次のように書かれているでしょう:
```Python
from unicorn import UnicornMiddleware
app = SomeASGIApp()
new_app = UnicornMiddleware(app, some_config="rainbow")
```
しかし FastAPI正確には Starletteは、内部ミドルウェアがサーバーエラーを処理し、カスタム例外ハンドラが正しく動作することを保証する、より簡単な方法を提供しています。
そのためにはCORS の例と同様に)`app.add_middleware()` を使います。
```Python
from fastapi import FastAPI
from unicorn import UnicornMiddleware
app = FastAPI()
app.add_middleware(UnicornMiddleware, some_config="rainbow")
```
`app.add_middleware()` は、最初の引数にミドルウェアのクラスを取り、それ以外の追加引数はミドルウェアに渡されます。
## 組み込みミドルウェア { #integrated-middlewares }
**FastAPI** は一般的なユースケースに対応するいくつかのミドルウェアを含んでいます。以下でその使い方を見ていきます。
/// note | 技術詳細
以下の例では、`from starlette.middleware.something import SomethingMiddleware` を使うこともできます。
**FastAPI** は開発者であるあなたの便宜のために `fastapi.middleware` にいくつかのミドルウェアを提供しています。しかし、利用可能なミドルウェアの多くは Starlette から直接提供されています。
///
## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware }
すべての受信リクエストが `https` または `wss` でなければならないように強制します。
`http` または `ws` への受信リクエストは、安全なスキームにリダイレクトされます。
{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *}
## `TrustedHostMiddleware` { #trustedhostmiddleware }
HTTP Host Header 攻撃を防ぐため、すべての受信リクエストに正しく設定された `Host` ヘッダーを強制します。
{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *}
サポートされる引数は次のとおりです:
- `allowed_hosts` - 許可するホスト名のドメイン名リスト。`*.example.com` のようなワイルドカードドメインでサブドメインのマッチングもサポートします。任意のホスト名を許可するには、`allowed_hosts=["*"]` を使うか、このミドルウェアを省略します。
- `www_redirect` - True に設定すると、許可されたホストの非 www 版へのリクエストを www 版へリダイレクトします。デフォルトは `True` です。
受信リクエストが正しく検証されない場合、`400` のレスポンスが返されます。
## `GZipMiddleware` { #gzipmiddleware }
`Accept-Encoding` ヘッダーに "gzip" を含むリクエストに対して GZip レスポンスを処理します。
このミドルウェアは、通常のレスポンスとストリーミングレスポンスの両方を処理します。
{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *}
サポートされる引数は次のとおりです:
- `minimum_size` - このバイト数の最小サイズ未満のレスポンスは GZip 圧縮しません。デフォルトは `500` です。
- `compresslevel` - GZip 圧縮時に使用します。1 から 9 までの整数です。デフォルトは `9`。値が小さいほど圧縮は速くなりますがファイルサイズは大きくなり、値が大きいほど圧縮は遅くなりますがファイルサイズは小さくなります。
## その他のミドルウェア { #other-middlewares }
他にも多くの ASGI ミドルウェアがあります。
例えば:
- <a href="https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py" class="external-link" target="_blank">Uvicorn の `ProxyHeadersMiddleware`</a>
- <a href="https://github.com/florimondmanca/msgpack-asgi" class="external-link" target="_blank">MessagePack</a>
他に利用可能なミドルウェアについては、<a href="https://www.starlette.dev/middleware/" class="external-link" target="_blank">Starlette のミドルウェアドキュメント</a><a href="https://github.com/florimondmanca/awesome-asgi" class="external-link" target="_blank">ASGI Awesome List</a> を参照してください。

View File

@ -0,0 +1,186 @@
# OpenAPI コールバック { #openapi-callbacks }
あなたは、*path operation* を持つ API を作成し、他者(多くの場合、あなたの API を「利用する」同一の開発者)が作成した *外部 API* へリクエストをトリガーできるようにできます。
あなたの API アプリが *外部 API* を呼び出すときに起きる処理は「コールバック」と呼ばれます。なぜなら、外部開発者が作成したソフトウェアがあなたの API にリクエストを送り、その後であなたの API が「呼び返し」、*外部 API*(おそらく同じ開発者が作成)へリクエストを送るためです。
この場合、その *外部 API* がどのようである「べき」かをドキュメント化したくなるでしょう。どんな *path operation* を持ち、どんなボディを受け取り、どんなレスポンスを返すか、などです。
## コールバックのあるアプリ { #an-app-with-callbacks }
例で見ていきます。
あなたが請求書を作成できるアプリを開発していると想像してください。
これらの請求書は `id`、`title`(任意)、`customer`、`total` を持ちます。
あなたの API の利用者外部開発者は、POST リクエストであなたの API に請求書を作成します。
その後、あなたの API は(仮にこうしましょう):
* 外部開発者の顧客に請求書を送ります。
* 代金を回収します。
* API 利用者(外部開発者)に通知を送り返します。
* これは(あなたの API から)外部開発者が提供する *外部 API* に POST リクエストを送ることで行われます(これが「コールバック」です)。
## 通常の FastAPI アプリ { #the-normal-fastapi-app }
まず、コールバックを追加する前の通常の API アプリがどうなるか見てみましょう。
`Invoice` ボディを受け取り、クエリパラメータ `callback_url` にコールバック用の URL を含める *path operation* を持ちます。
この部分はとても普通で、ほとんどのコードはすでに見覚えがあるはずです:
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *}
/// tip | 豆知識
`callback_url` クエリパラメータは、Pydantic の <a href="https://docs.pydantic.dev/latest/api/networks/" class="external-link" target="_blank">Url</a> 型を使用します。
///
唯一の新しい点は、*path operation デコレータ*の引数として `callbacks=invoices_callback_router.routes` を渡すことです。これが何かは次で見ます。
## コールバックのドキュメント化 { #documenting-the-callback }
実際のコールバックのコードは、あなた自身の API アプリに大きく依存します。
そしてアプリごとに大きく異なるでしょう。
それは次のように 1、2 行のコードかもしれません:
```Python
callback_url = "https://example.com/api/v1/invoices/events/"
httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
```
しかし、おそらくコールバックで最も重要な点は、あなたの API 利用者(外部開発者)が、*あなたの API* がコールバックのリクエストボディなどで送るデータに従って、*外部 API* を正しく実装することを確実にすることです。
そこで次に行うのは、*あなたの API* からのコールバックを受け取るために、その *外部 API* がどうあるべきかをドキュメント化するコードを追加することです。
そのドキュメントはあなたの API の `/docs` の Swagger UI に表示され、外部開発者に *外部 API* の作り方を知らせます。
この例ではコールバック自体は実装しません(それは 1 行のコードでもよいでしょう)。ドキュメント部分のみです。
/// tip | 豆知識
実際のコールバックは単なる HTTP リクエストです。
自分でコールバックを実装する場合は、<a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a><a href="https://requests.readthedocs.io/" class="external-link" target="_blank">Requests</a> のようなものを使えます。
///
## コールバックのドキュメント用コードを書く { #write-the-callback-documentation-code }
このコードはあなたのアプリで実行されません。*外部 API* がどうあるべきかをドキュメント化するためだけに必要です。
しかし、あなたはすでに **FastAPI** で API の自動ドキュメントを簡単に作る方法を知っています。
その知識を使って、*外部 API* がどうあるべきかをドキュメント化します……つまり、外部 API が実装すべき *path operation(s)*(あなたの API が呼び出すもの)を作成します。
/// tip | 豆知識
コールバックをドキュメント化するコードを書くときは、あなたがその「外部開発者」だと想像するのが役に立つかもしれません。いま実装しているのは「あなたの API」ではなく、*外部 API* です。
この(外部開発者の)視点を一時的に採用すると、その *外部 API* に対してパラメータ、ボディ用の Pydantic モデル、レスポンスなどをどこに置くのが自然かがより明確に感じられるでしょう。
///
### コールバック用 APIRouter を作成 { #create-a-callback-apirouter }
まず、1 つ以上のコールバックを含む新しい `APIRouter` を作成します。
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *}
### コールバックの path operation を作成 { #create-the-callback-path-operation }
上で作成したのと同じ `APIRouter` を使って、コールバックの *path operation* を作成します。
見た目は通常の FastAPI の *path operation* と同じです:
* 受け取るボディの宣言(例: `body: InvoiceEvent`)が必要でしょう。
* 返すレスポンスの宣言(例: `response_model=InvoiceEventReceived`)も持てます。
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *}
通常の *path operation* と異なる主な点が 2 つあります:
* 実際のコードは不要です。あなたのアプリはこのコードを決して呼びません。これは *外部 API* をドキュメント化するためだけに使われます。したがって、関数本体は `pass` で構いません。
* *パス* には、*あなたの API* に送られた元のリクエストのパラメータや一部を変数として使える <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">OpenAPI 3 の式</a>(後述)を含められます。
### コールバックのパス式 { #the-callback-path-expression }
コールバックの *パス* には、*あなたの API* に送られた元のリクエストの一部を含められる <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression" class="external-link" target="_blank">OpenAPI 3 の式</a>を使用できます。
この例では、`str` は次のとおりです:
```Python
"{$callback_url}/invoices/{$request.body.id}"
```
つまり、あなたの API 利用者(外部開発者)が *あなたの API* に次のようにリクエストを送った場合:
```
https://yourapi.com/invoices/?callback_url=https://www.external.org/events
```
JSON ボディは:
```JSON
{
"id": "2expen51ve",
"customer": "Mr. Richie Rich",
"total": "9999"
}
```
その後 *あなたの API* は請求書を処理し、のちほど `callback_url`*外部 API*)へコールバックのリクエストを送ります:
```
https://www.external.org/events/invoices/2expen51ve
```
JSON ボディは次のような内容です:
```JSON
{
"description": "Payment celebration",
"paid": true
}
```
そして *外部 API* からは次のような JSON ボディのレスポンスを期待します:
```JSON
{
"ok": true
}
```
/// tip | 豆知識
使用されるコールバック URL には、クエリパラメータ `callback_url``https://www.external.org/events`)で受け取った URL と、JSON ボディ内の請求書 `id``2expen51ve`)が含まれている点に注目してください。
///
### コールバック用ルーターを追加 { #add-the-callback-router }
これで、上で作成したコールバック用ルーター内に、必要なコールバックの *path operation(s)**外部開発者* が *外部 API* に実装すべきもの)が用意できました。
次に、*あなたの API の path operation デコレータ*の `callbacks` パラメータに、そのコールバック用ルーターの属性 `.routes`(実体はルート/*path operations* の `list`)を渡します:
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *}
/// tip | 豆知識
`callback=` に渡すのはルーター本体(`invoices_callback_router`)ではなく、属性 `.routes``invoices_callback_router.routes`)である点に注意してください。
///
### ドキュメントを確認 { #check-the-docs }
アプリを起動して <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> にアクセスします。
あなたの *path operation* に「Callbacks」セクションが含まれ、*外部 API* がどうあるべきかが表示されているのが確認できます:
<img src="/img/tutorial/openapi-callbacks/image01.png">

View File

@ -0,0 +1,55 @@
# OpenAPI の Webhook { #openapi-webhooks }
アプリがある種の**イベント**を**通知**するために、データ付きで相手のアプリリクエスト送信を呼び出す可能性があることを、API の**ユーザー**に伝えたい場合があります。
これは、通常のようにユーザーがあなたの API にリクエストを送るのではなく、**あなたの APIあなたのアプリ**が**相手のシステム**(相手の API、アプリにリクエストを送る、ということです。
これは一般に**Webhook**と呼ばれます。
## Webhook の手順 { #webhooks-steps }
通常の流れとして、まずあなたのコード内で、送信するメッセージ、すなわちリクエストの**本文(ボディ)**を**定義**します。
加えて、アプリがそれらのリクエスト(イベント)を送信する**タイミング**も何らかの形で定義します。
そして**ユーザー**は、アプリがそのリクエストを送るべき**URL**を(たとえばどこかの Web ダッシュボードで)定義します。
Webhook の URL を登録する方法や実際にリクエストを送るコードなど、これらの**ロジック**はすべてあなた次第です。**あなた自身のコード**で好きなように実装します。
## FastAPI と OpenAPI による Webhook のドキュメント化 { #documenting-webhooks-with-fastapi-and-openapi }
**FastAPI** と OpenAPI を使うと、Webhook の名前、アプリが送信できる HTTP の操作(例: `POST`, `PUT` など)、アプリが送るリクエストの**ボディ**を定義できます。
これにより、ユーザーがあなたの **Webhook** リクエストを受け取るための**API を実装**するのが大幅に簡単になります。場合によっては、ユーザーが自分たちの API コードを自動生成できるかもしれません。
/// info | 情報
Webhook は OpenAPI 3.1.0 以上で利用可能で、FastAPI `0.99.0` 以上が対応しています。
///
## Webhook を持つアプリ { #an-app-with-webhooks }
**FastAPI** アプリケーションを作成すると、`webhooks` という属性があり、ここで *path operations* と同様に(例: `@app.webhooks.post()`*webhook* を定義できます。
{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *}
定義した webhook は **OpenAPI** スキーマおよび自動生成される **ドキュメント UI** に反映されます。
/// info | 情報
`app.webhooks` オブジェクトは実際には単なる `APIRouter` で、複数ファイルでアプリを構成する際に使うものと同じ型です。
///
Webhook では(`/items/` のような)*パス*を宣言しているわけではない点に注意してください。ここで渡す文字列は webhook の**識別子**(イベント名)です。たとえば `@app.webhooks.post("new-subscription")` での webhook 名は `new-subscription` です。
これは、**ユーザー**が実際に Webhook リクエストを受け取りたい**URL パス**を、別の方法(例: Web ダッシュボード)で定義することを想定しているためです。
### ドキュメントの確認 { #check-the-docs }
アプリを起動し、<a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> にアクセスします。
ドキュメントには通常の *path operations* に加えて、**webhooks** も表示されます:
<img src="/img/tutorial/openapi-webhooks/image01.png">

View File

@ -12,7 +12,7 @@ OpenAPIの「エキスパート」でなければ、これはおそらく必要
各オペレーションで一意になるようにする必要があります。
{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py39.py hl[6] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *}
### *path operation関数* の名前をoperationIdとして使用する { #using-the-path-operation-function-name-as-the-operationid }
@ -20,7 +20,7 @@ APIの関数名を `operationId` として利用したい場合、すべてのAP
すべての *path operation* を追加した後に行うべきです。
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py39.py hl[2, 12:21, 24] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2, 12:21, 24] *}
/// tip | 豆知識
@ -40,7 +40,7 @@ APIの関数名を `operationId` として利用したい場合、すべてのAP
生成されるOpenAPIスキーマつまり、自動ドキュメント生成の仕組みから *path operation* を除外するには、`include_in_schema` パラメータを使用して `False` に設定します。
{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py39.py hl[6] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *}
## docstringによる説明の高度な設定 { #advanced-description-from-docstring }
@ -92,7 +92,7 @@ OpenAPI仕様では <a href="https://github.com/OAI/OpenAPI-Specification/blob/m
この `openapi_extra` は、例えば [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) を宣言するのに役立ちます。
{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py39.py hl[6] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *}
自動APIドキュメントを開くと、その拡張は特定の *path operation* の下部に表示されます。
@ -139,9 +139,9 @@ OpenAPI仕様では <a href="https://github.com/OAI/OpenAPI-Specification/blob/m
それは `openapi_extra` で行えます。
{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py39.py hl[19:36, 39:40] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *}
この例では、Pydanticモデルを一切宣言していません。実際、リクエストボディはJSONとして <abbr title="converted from some plain format, like bytes, into Python objects bytesなどのプレーンな形式からPythonオブジェクトに変換すること">parsed</abbr> されず、直接 `bytes` として読み取られます。そして `magic_data_reader()` 関数が、何らかの方法でそれをパースする責務を担います。
この例では、Pydanticモデルを一切宣言していません。実際、リクエストボディはJSONとして <dfn title="bytes などのプレーンな形式から Python オブジェクトに変換される">パース</dfn> されず、直接 `bytes` として読み取られます。そして `magic_data_reader()` 関数が、何らかの方法でそれをパースする責務を担います。
それでも、リクエストボディに期待されるスキーマを宣言できます。
@ -153,7 +153,7 @@ OpenAPI仕様では <a href="https://github.com/OAI/OpenAPI-Specification/blob/m
例えばこのアプリケーションでは、PydanticモデルからJSON Schemaを抽出するFastAPIの統合機能や、JSONの自動バリデーションを使っていません。実際、リクエストのcontent typeをJSONではなくYAMLとして宣言しています。
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[15:20, 22] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *}
それでも、デフォルトの統合機能を使っていないにもかかわらず、YAMLで受け取りたいデータのために、Pydanticモデルを使って手動でJSON Schemaを生成しています。
@ -161,7 +161,7 @@ OpenAPI仕様では <a href="https://github.com/OAI/OpenAPI-Specification/blob/m
その後、コード内でそのYAMLコンテンツを直接パースし、さらに同じPydanticモデルを使ってYAMLコンテンツを検証しています。
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py39.py hl[24:31] *}
{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *}
/// tip | 豆知識

View File

@ -0,0 +1,31 @@
# レスポンス - ステータスコードの変更 { #response-change-status-code }
すでに、デフォルトの[レスポンスのステータスコード](../tutorial/response-status-code.md){.internal-link target=_blank}を設定できることをご存知かもしれません。
しかし場合によっては、デフォルトとは異なるステータスコードを返す必要があります。
## ユースケース { #use-case }
たとえば、デフォルトでは HTTP ステータスコード "OK" `200` を返したいとします。
しかし、データが存在しなければそれを作成し、HTTP ステータスコード "CREATED" `201` を返したい。
それでも、返すデータは `response_model` でフィルタ・変換できるようにしておきたい。
そのような場合は `Response` パラメータを使えます。
## `Response` パラメータを使う { #use-a-response-parameter }
*path operation* 関数で `Response` 型のパラメータを宣言できますCookie やヘッダーと同様です)。
そして、その*一時的な*レスポンスオブジェクトに `status_code` を設定できます。
{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *}
その後は通常どおり、必要な任意のオブジェクト(`dict`、データベースモデルなど)を返せます。
そして `response_model` を宣言していれば、返したオブジェクトのフィルタと変換には引き続きそれが使われます。
FastAPI はその*一時的な*レスポンスからステータスコード(および Cookie とヘッダー)を取り出し、`response_model` によってフィルタ済みの返却値を含む最終的なレスポンスに反映します。
また、`Response` パラメータは依存関係内に宣言してステータスコードを設定することもできます。ただし、最後に設定されたものが優先される点に注意してください。

View File

@ -0,0 +1,51 @@
# レスポンスの Cookie { #response-cookies }
## `Response` パラメータを使う { #use-a-response-parameter }
*path operation 関数*で `Response` 型のパラメータを宣言できます。
そして、その*一時的*なレスポンスオブジェクトに Cookie を設定できます。
{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *}
その後は通常どおり、必要な任意のオブジェクト(`dict`、データベースモデルなど)を返せます。
`response_model` を宣言している場合でも、返したオブジェクトは引き続きフィルタおよび変換されます。
**FastAPI** はその*一時的*なレスポンスから Cookieおよびヘッダーやステータスコードを取り出し、`response_model` によってフィルタされた返却値を含む最終的なレスポンスに設定します。
`Response` パラメータは依存関係でも宣言でき、そこで Cookieやヘッダーを設定することも可能です。
## `Response` を直接返す { #return-a-response-directly }
コードで `Response` を直接返すときに、Cookie を作成することもできます。
そのためには、[Response を直接返す](response-directly.md){.internal-link target=_blank} で説明されているとおりにレスポンスを作成します。
そのレスポンスに Cookie を設定してから返します:
{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *}
/// tip | 豆知識
`Response` パラメータを使わずにレスポンスを直接返す場合、FastAPI はそのレスポンスをそのまま返します。
そのため、データの型が正しいことを確認する必要があります。例えば、`JSONResponse` を返すなら、JSON と互換性がある必要があります。
また、`response_model` によってフィルタされるべきデータを送っていないことも確認してください。
///
### 詳細情報 { #more-info }
/// note | 技術詳細
`from starlette.responses import Response``from starlette.responses import JSONResponse` を使うこともできます。
**FastAPI** は開発者の利便性のために、`starlette.responses` と同じものを `fastapi.responses` として提供しています。ただし、利用可能なレスポンスの大半は Starlette から直接提供されています。
また、`Response` はヘッダーや Cookie の設定に頻繁に使われるため、`fastapi.Response` としても提供されています。
///
利用可能なすべてのパラメータやオプションについては、<a href="https://www.starlette.dev/responses/#set-cookie" class="external-link" target="_blank">Starlette のドキュメント</a>を参照してください。

View File

@ -54,7 +54,7 @@
XMLを文字列にし、`Response` に含め、それを返します。
{* ../../docs_src/response_directly/tutorial002_py39.py hl[1,18] *}
{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
## 備考 { #notes }

View File

@ -0,0 +1,41 @@
# レスポンスヘッダー { #response-headers }
## `Response` パラメータを使う { #use-a-response-parameter }
Cookie と同様に)*path operation 関数*で `Response` 型のパラメータを宣言できます。
そして、その*一時的*なレスポンスオブジェクトにヘッダーを設定できます。
{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *}
その後は通常どおり、必要な任意のオブジェクト(`dict`、データベースモデルなど)を返せます。
`response_model` を宣言している場合は、返したオブジェクトのフィルタと変換に引き続き使用されます。
**FastAPI** はその*一時的*なレスポンスからヘッダーCookie やステータスコードも含む)を取り出し、`response_model` によってフィルタされた返却値を含む最終的なレスポンスに反映します。
また、依存関係の中で `Response` パラメータを宣言し、その中でヘッダー(や Cookieを設定することもできます。
## `Response` を直接返す { #return-a-response-directly }
`Response` を直接返す場合にもヘッダーを追加できます。
[Response を直接返す](response-directly.md){.internal-link target=_blank} で説明したようにレスポンスを作成し、ヘッダーを追加のパラメータとして渡します:
{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *}
/// note | 技術詳細
`from starlette.responses import Response``from starlette.responses import JSONResponse` を使うこともできます。
**FastAPI** は、開発者であるあなたへの便宜として、`starlette.responses` と同じものを `fastapi.responses` として提供しています。しかし、利用可能なレスポンスの大半は直接 Starlette から来ています。
また、`Response` はヘッダーや Cookie を設定するのによく使われるため、**FastAPI** は `fastapi.Response` でも提供しています。
///
## カスタムヘッダー { #custom-headers }
独自のカスタムヘッダーは、<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">`X-` プレフィックスを使って</a>追加できることに注意してください。
ただし、ブラウザのクライアントに見えるようにしたいカスタムヘッダーがある場合は、CORS 設定にそれらを追加する必要があります([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md){.internal-link target=_blank} を参照)。このとき、<a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">Starlette の CORS ドキュメント</a>に記載の `expose_headers` パラメータを使用します。

View File

@ -0,0 +1,107 @@
# HTTP Basic 認証 { #http-basic-auth }
最もシンプルなケースでは、HTTP Basic 認証を利用できます。
HTTP Basic 認証では、アプリケーションはユーザー名とパスワードを含むヘッダーを期待します。
それを受け取れない場合、HTTP 401 "Unauthorized" エラーを返します。
そして、値が `Basic` のヘッダー `WWW-Authenticate` を、任意の `realm` パラメータとともに返します。
これにより、ブラウザは組み込みのユーザー名とパスワード入力プロンプトを表示します。
その後、そのユーザー名とパスワードを入力すると、ブラウザはそれらをヘッダーに自動的に付与して送信します。
## シンプルな HTTP Basic 認証 { #simple-http-basic-auth }
- `HTTPBasic``HTTPBasicCredentials` をインポートします。
- `HTTPBasic` を使って「`security` スキーム」を作成します。
- その `security` を依存関係として path operation に使用します。
- `HTTPBasicCredentials` 型のオブジェクトが返ります:
- 送信された `username``password` を含みます。
{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *}
URL を最初に開こうとしたときまたはドキュメントで「Execute」ボタンをクリックしたとき、ブラウザはユーザー名とパスワードの入力を求めます:
<img src="/img/tutorial/security/image12.png">
## ユーザー名の確認 { #check-the-username }
より完全な例です。
依存関係を使ってユーザー名とパスワードが正しいかを確認します。
これには、Python 標準モジュール <a href="https://docs.python.org/3/library/secrets.html" class="external-link" target="_blank">`secrets`</a> を用いてユーザー名とパスワードを検証します。
`secrets.compare_digest()``bytes` か、ASCII 文字(英語の文字)のみを含む `str` を受け取る必要があります。つまり、`Sebastián` のように `á` を含む文字ではそのままでは動作しません。
これに対処するため、まず `username``password` を UTF-8 でエンコードして `bytes` に変換します。
そのうえで、`secrets.compare_digest()` を使って、`credentials.username` が `"stanleyjobson"` であり、`credentials.password` が `"swordfish"` であることを確認します。
{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *}
これは次のようなコードに相当します:
```Python
if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
# Return some error
...
```
しかし `secrets.compare_digest()` を使うことで、「タイミング攻撃」と呼ばれる種類の攻撃に対して安全になります。
### タイミング攻撃 { #timing-attacks }
「タイミング攻撃」とは何でしょうか?
攻撃者がユーザー名とパスワードを推測しようとしていると想像してください。
そして、ユーザー名 `johndoe`、パスワード `love123` を使ってリクエストを送ります。
その場合、アプリケーション内の Python コードは次のようなものと等価になります:
```Python
if "johndoe" == "stanleyjobson" and "love123" == "swordfish":
...
```
しかし、Python は `johndoe` の最初の `j``stanleyjobson` の最初の `s` を比較した時点で、両者の文字列が同じでないと判断してすぐに `False` を返します。つまり「残りの文字を比較して計算資源を無駄にする必要はない」と考えるわけです。そしてアプリケーションは「ユーザー名またはパスワードが正しくありません」と返します。
次に、攻撃者がユーザー名 `stanleyjobsox`、パスワード `love123` で試すとします。
アプリケーションのコードは次のようになります:
```Python
if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish":
...
```
この場合、Python は `stanleyjobsox``stanleyjobson` の両方で `stanleyjobso` 全体を比較してから、文字列が同じでないと気づきます。したがって、「ユーザー名またはパスワードが正しくありません」と応答するまでに余分に数マイクロ秒かかります。
#### 応答時間が攻撃者を助ける { #the-time-to-answer-helps-the-attackers }
ここで、サーバーが「ユーザー名またはパスワードが正しくありません」というレスポンスを返すまでに、わずかに長い時間がかかったことに気づけば、攻撃者は何かしら正解に近づいた、すなわち先頭のいくつかの文字が正しかったことを知ることができます。
すると、`johndoe` よりも `stanleyjobsox` に近いものを狙って再試行できます。
#### 「プロ」レベルの攻撃 { #a-professional-attack }
もちろん、攻撃者はこれらを手作業では行わず、プログラムを書いて、1 秒間に数千〜数百万回のテストを行うでしょう。そして 1 回に 1 文字ずつ正しい文字を見つけていきます。
そうすることで、数分から数時間のうちに、攻撃者は私たちのアプリケーションの「助け」(応答にかかった時間)だけを利用して、正しいユーザー名とパスワードを推測できてしまいます。
#### `secrets.compare_digest()` で対策 { #fix-it-with-secrets-compare-digest }
しかし、私たちのコードでは実際に `secrets.compare_digest()` を使用しています。
要するに、`stanleyjobsox` と `stanleyjobson` を比較するのにかかる時間は、`johndoe` と `stanleyjobson` を比較するのにかかる時間と同じになります。パスワードでも同様です。
このように、アプリケーションコードで `secrets.compare_digest()` を使うと、この種の一連のセキュリティ攻撃に対して安全になります。
### エラーを返す { #return-the-error }
認証情報が不正であることを検出したら、ステータスコード 401認証情報が提供されない場合と同じ`HTTPException` を返し、ブラウザに再度ログインプロンプトを表示させるためにヘッダー `WWW-Authenticate` を追加します:
{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *}

View File

@ -0,0 +1,19 @@
# 高度なセキュリティ { #advanced-security }
## 追加機能 { #additional-features }
[チュートリアル - ユーザーガイド: セキュリティ](../../tutorial/security/index.md){.internal-link target=_blank}で扱ったもの以外にも、セキュリティを扱うための追加機能がいくつかあります。
/// tip | 豆知識
次の節は必ずしも「高度」ではありません。
あなたのユースケースでは、その中のいずれかに解決策があるかもしれません。
///
## まずチュートリアルを読む { #read-the-tutorial-first }
以下の節は、すでにメインの[チュートリアル - ユーザーガイド: セキュリティ](../../tutorial/security/index.md){.internal-link target=_blank}を読んでいることを前提とします。
いずれも同じ概念に基づいていますが、いくつかの追加機能を利用できます。

View File

@ -0,0 +1,274 @@
# OAuth2 のスコープ { #oauth2-scopes }
OAuth2 のスコープは **FastAPI** で直接利用でき、シームレスに統合されています。
これにより、OAuth2 標準に従った、よりきめ細かな権限システムを、OpenAPI 対応アプリケーション(および API ドキュメント)に統合できます。
スコープ付きの OAuth2 は、Facebook、Google、GitHub、Microsoft、X (Twitter) など、多くの大手認証プロバイダで使われている仕組みです。ユーザーやアプリケーションに特定の権限を付与するために利用されます。
「Facebook でログイン」「Google でログイン」「GitHub でログイン」「Microsoft でログイン」「X (Twitter) でログイン」するたびに、そのアプリケーションはスコープ付きの OAuth2 を使っています。
この節では、同じスコープ付き OAuth2 を使って、**FastAPI** アプリケーションで認証と認可を管理する方法を見ていきます。
/// warning | 注意
これはやや高度な内容です。はじめたばかりであれば読み飛ばしても構いません。
OAuth2 のスコープは必ずしも必要ではなく、認証と認可は好きなやり方で実装できます。
ただし、スコープ付きの OAuth2 は、APIOpenAPIや API ドキュメントにきれいに統合できます。
とはいえ、これらのスコープやその他のセキュリティ/認可要件の適用は、必要に応じてコードの中で行う必要があります。
多くの場合、スコープ付き OAuth2 はオーバースペックになりえます。
それでも必要だと分かっている場合や、興味がある場合は、このまま読み進めてください。
///
## OAuth2 のスコープと OpenAPI { #oauth2-scopes-and-openapi }
OAuth2 仕様では、「スコープ」は空白で区切られた文字列の一覧として定義されています。
各文字列の内容は任意ですが、空白は含められません。
これらのスコープは「権限」を表します。
OpenAPI例: API ドキュメント)では、「セキュリティスキーム」を定義できます。
これらのセキュリティスキームの一つが OAuth2 を使う場合、スコープを宣言して利用できます。
各「スコープ」は、ただの文字列(空白なし)です。
通常、特定のセキュリティ権限を宣言するために使われます。例えば:
- `users:read``users:write` は一般的な例です。
- `instagram_basic` は Facebook / Instagram で使われています。
- `https://www.googleapis.com/auth/drive` は Google で使われています。
/// info | 情報
OAuth2 において「スコープ」は、必要な特定の権限を宣言する単なる文字列です。
`:` のような他の文字が含まれていても、URL であっても問題ありません。
それらの詳細は実装依存です。
OAuth2 にとっては、単に文字列に過ぎません。
///
## 全体像 { #global-view }
まず、メインの**チュートリアル - ユーザーガイド**にある [OAuth2パスワードハッシュ化あり、Bearer と JWT トークン](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank} の例から変更される部分を、スコープ付き OAuth2 を使って手早く見てみましょう。
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *}
では、これらの変更を一つずつ確認していきます。
## OAuth2 のセキュリティスキーム { #oauth2-security-scheme }
最初の変更点は、`me` と `items` の 2 つのスコープを持つ OAuth2 セキュリティスキームを宣言していることです。
`scopes` パラメータは、各スコープをキー、その説明を値とする `dict` を受け取ります:
{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *}
これらのスコープを宣言しているため、ログイン/認可時に API ドキュメントに表示されます。
そして、付与するスコープ(`me`、`items`)を選択できます。
これは、Facebook、Google、GitHub などでログイン時に権限を付与する際と同じ仕組みです:
<img src="/img/tutorial/security/image11.png">
## スコープ付きの JWT トークン { #jwt-token-with-scopes }
次に、トークンの path operation を修正して、要求されたスコープを返すようにします。
引き続き同じ `OAuth2PasswordRequestForm` を使用します。これには、リクエストで受け取った各スコープを含む、`str` の `list` である `scopes` プロパティが含まれます。
そして、そのスコープを JWT トークンの一部として返します。
/// danger | 警告
簡単のため、ここでは受け取ったスコープをそのままトークンに追加しています。
しかし、本番アプリケーションではセキュリティのため、ユーザーが実際に持つことができるスコープ、または事前に定義したスコープだけを追加するようにしてください。
///
{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *}
## path operation と依存関係でスコープを宣言 { #declare-scopes-in-path-operations-and-dependencies }
ここでは、`/users/me/items/` の path operation が `items` スコープを必要とするように宣言します。
そのために、`fastapi` から `Security` をインポートして使います。
`Security` は(`Depends` と同様に)依存関係を宣言できますが、さらにスコープ(文字列)のリストを受け取る `scopes` パラメータも持ちます。
この場合、`Security` に依存関数 `get_current_active_user` を渡します(`Depends` と同様です)。
加えて、`items` という 1 つのスコープ(複数でも可)を含む `list` も渡します。
依存関数 `get_current_active_user` は、`Depends` だけでなく `Security` でもサブ依存関係を宣言できます。自身のサブ依存関数(`get_current_user`)を宣言し、さらにスコープ要件を追加します。
この場合、`me` スコープを要求します(複数のスコープも可)。
/// note | 備考
異なる場所で異なるスコープを追加する必要は必ずしもありません。
ここでは、**FastAPI** が異なるレベルで宣言されたスコープをどのように扱うかを示すためにそうしています。
///
{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *}
/// info | 技術詳細
`Security` は実際には `Depends` のサブクラスで、後述する追加パラメータが 1 つあるだけです。
しかし `Depends` の代わりに `Security` を使うことで、**FastAPI** はセキュリティスコープを宣言・内部利用でき、OpenAPI で API をドキュメント化できると判断します。
なお、`fastapi` から `Query`、`Path`、`Depends`、`Security` などをインポートする際、それらは実際には特殊なクラスを返す関数です。
///
## `SecurityScopes` を使う { #use-securityscopes }
次に、依存関数 `get_current_user` を更新します。
これは上記の依存関係から使用されます。
ここで、先ほど作成した同じ OAuth2 スキームを依存関係(`oauth2_scheme`)として宣言して使います。
この依存関数自体はスコープ要件を持たないため、`oauth2_scheme` には `Depends` を使えます。セキュリティスコープを指定する必要がない場合は `Security` を使う必要はありません。
さらに、`fastapi.security` からインポートする特別な型 `SecurityScopes` のパラメータを宣言します。
この `SecurityScopes` クラスは `Request` に似ています(`Request` はリクエストオブジェクトを直接取得するために使いました)。
{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *}
## `scopes` を使う { #use-the-scopes }
パラメータ `security_scopes``SecurityScopes` 型になります。
このオブジェクトは、自身およびこれをサブ依存として使うすべての依存関係で要求されるスコープを含む `scopes` プロパティ(リスト)を持ちます。つまり、すべての「依存元」... 少し分かりにくいかもしれませんが、後で再度説明します。
`security_scopes``SecurityScopes` クラスのインスタンス)は、要求されたスコープを空白で連結した 1 つの文字列を返す `scope_str` も提供します(これを使います)。
後で複数箇所で再利用raiseできるように、`HTTPException` を 1 つ作成します。
この例外には、要求されたスコープがあればそれらを空白区切りの文字列(`scope_str` を使用)として含めます。このスコープ文字列は `WWW-Authenticate` ヘッダに入れます(仕様の一部です)。
{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *}
## `username` とデータ構造の検証 { #verify-the-username-and-data-shape }
`username` を取得できていることを確認し、スコープを取り出します。
そして、そのデータを Pydantic モデルで検証します(`ValidationError` 例外を捕捉。JWT トークンの読み取りや Pydantic によるデータ検証でエラーが発生した場合は、先ほど作成した `HTTPException` を送出します。
そのために、Pydantic モデル `TokenData` に新しいプロパティ `scopes` を追加します。
Pydantic でデータを検証することで、例えばスコープは `str``list`、`username` は `str` といった、正確な型になっていることを保証できます。
そうしておけば、例えば誤って `dict` などが入って後でアプリケーションを破壊してしまい、セキュリティリスクになる、といった事態を避けられます。
また、その `username` を持つユーザーが存在することも確認し、存在しなければ、やはり先ほどの例外を送出します。
{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *}
## `scopes` の検証 { #verify-the-scopes }
この依存関数およびすべての依存元path operation を含む)が要求するすべてのスコープが、受け取ったトークンに含まれていることを検証し、含まれていなければ `HTTPException` を送出します。
そのために、これらすべてのスコープを `str``list` として含む `security_scopes.scopes` を使います。
{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *}
## 依存関係ツリーとスコープ { #dependency-tree-and-scopes }
依存関係ツリーとスコープをもう一度見てみましょう。
`get_current_active_user` 依存関係は `get_current_user` をサブ依存として持つため、`get_current_active_user` で宣言された `"me"` スコープは、`get_current_user` に渡される `security_scopes.scopes` の必須スコープ一覧に含まれます。
path operation 自体も `"items"` スコープを宣言するため、これも `get_current_user` に渡される `security_scopes.scopes` に含まれます。
依存関係とスコープの階層は次のようになります:
- *path operation* `read_own_items` には:
- 依存関係に対して必須スコープ `["items"]` がある:
- `get_current_active_user`:
- 依存関数 `get_current_active_user` には:
- 依存関係に対して必須スコープ `["me"]` がある:
- `get_current_user`:
- 依存関数 `get_current_user` には:
- 自身に必須スコープはない。
- `oauth2_scheme` を使う依存関係がある。
- `SecurityScopes` 型の `security_scopes` パラメータがある:
- この `security_scopes` パラメータは、上で宣言されたすべてのスコープを含む `list` を持つ `scopes` プロパティを持つ。したがって:
- *path operation* `read_own_items` では、`security_scopes.scopes` は `["me", "items"]` を含む。
- *path operation* `read_users_me` では、`security_scopes.scopes` は `["me"]` を含む。これは依存関係 `get_current_active_user` に宣言されているため。
- *path operation* `read_system_status` では、`security_scopes.scopes` は `[]`(空)になる。`scopes` を持つ `Security` を宣言しておらず、その依存関係 `get_current_user``scopes` を宣言していないため。
/// tip | 豆知識
重要で「魔法のよう」な点は、`get_current_user` が path operation ごとに異なる `scopes` のリストをチェックすることになる、ということです。
それは、それぞれの path operation と、その path operation の依存関係ツリー内の各依存関係で宣言された `scopes` によって決まります。
///
## `SecurityScopes` の詳細 { #more-details-about-securityscopes }
`SecurityScopes` はどの地点でも、複数箇所でも使えます。「ルート」の依存関係である必要はありません。
常に、その時点の `Security` 依存関係と、**その特定の** path operation と **その特定の** 依存関係ツリーにおける、すべての依存元で宣言されたセキュリティスコープを持ちます。
`SecurityScopes` には依存元で宣言されたすべてのスコープが入るため、トークンが必要なスコープを持っているかどうかを中央の依存関数で検証し、path operation ごとに異なるスコープ要件を宣言する、といった使い方ができます。
これらは path operation ごとに独立して検証されます。
## チェック { #check-it }
API ドキュメントを開くと、認証して、許可するスコープを指定できます。
<img src="/img/tutorial/security/image11.png">
どのスコープも選択しない場合は「認証済み」にはなりますが、`/users/me/` や `/users/me/items/` にアクセスしようとすると、権限が不足しているというエラーになります。`/status/` には引き続きアクセスできます。
`me` スコープだけを選択し、`items` スコープを選択しない場合は、`/users/me/` にはアクセスできますが、`/users/me/items/` にはアクセスできません。
これは、ユーザーがアプリケーションに与えた権限の範囲に応じて、サードパーティアプリケーションがこれらの path operation のいずれかに、ユーザーから提供されたトークンでアクセスしようとしたときに起こる動作です。
## サードパーティ統合について { #about-third-party-integrations }
この例では、OAuth2 の「password」フローを使用しています。
これは、(おそらく自前のフロントエンドで)自分たちのアプリケーションにログインする場合に適しています。
自分たちで管理しているため、`username` と `password` を受け取る相手を信頼できるからです。
しかし、他者が接続する OAuth2 アプリケーションFacebook、Google、GitHub などに相当する認証プロバイダ)を構築する場合は、他のいずれかのフローを使用すべきです。
最も一般的なのは implicit フローです。
最も安全なのは code フローですが、手順が多く実装がより複雑です。複雑なため、多くのプロバイダは結局 implicit フローを推奨することがあります。
/// note | 備考
各認証プロバイダがフローに独自の名称を付け、自社のブランドの一部にするのは一般的です。
しかし、最終的には同じ OAuth2 標準を実装しています。
///
**FastAPI** には、これらすべての OAuth2 認証フロー向けのユーティリティが `fastapi.security.oauth2` に含まれています。
## デコレータ `dependencies` での `Security` { #security-in-decorator-dependencies }
デコレータの `dependencies` パラメータに `Depends``list` を定義できるのと同様([path operation デコレータでの依存関係](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} 参照)、ここで `scopes` を指定した `Security` も使用できます。

View File

@ -0,0 +1,302 @@
# 設定と環境変数 { #settings-and-environment-variables }
多くの場合、アプリケーションは外部の設定や構成を必要とします。たとえば、シークレットキー、データベース認証情報、メールサービスの認証情報などです。
これらの設定の多くは可変変更されうるで、データベースのURLのようなものがあります。また、多くはシークレットのように機微な情報です。
そのため、アプリケーションが読み取る環境変数で提供するのが一般的です。
/// tip | 豆知識
環境変数について理解するには、[環境変数](../environment-variables.md){.internal-link target=_blank}を参照してください。
///
## 型とバリデーション { #types-and-validation }
これらの環境変数は Python の外部にあり、他のプログラムやシステム全体Linux、Windows、macOS といった異なるOSを含むと互換性が必要なため、文字列テキストのみを扱えます。
つまり、Python で環境変数から読み取られる値はすべて `str` になり、他の型への変換やバリデーションはコードで行う必要があります。
## Pydantic の `Settings` { #pydantic-settings }
幸いなことに、Pydantic には環境変数から来る設定を扱うための優れたユーティリティがあり、<a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/" class="external-link" target="_blank">Pydantic: Settings management</a> で提供されています。
### `pydantic-settings` のインストール { #install-pydantic-settings }
まず、[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成して有効化し、`pydantic-settings` パッケージをインストールします:
<div class="termy">
```console
$ pip install pydantic-settings
---> 100%
```
</div>
また、次のように `all` エクストラをインストールすると付属します:
<div class="termy">
```console
$ pip install "fastapi[all]"
---> 100%
```
</div>
### `Settings` オブジェクトを作成 { #create-the-settings-object }
Pydantic から `BaseSettings` をインポートして、そのサブクラスを作成します。これは Pydantic モデルとほぼ同じです。
Pydantic モデルと同様に、型アノテーションと(必要なら)デフォルト値を持つクラス属性を宣言します。
`Field()` による追加バリデーションなど、Pydantic モデルで使えるのと同じバリデーション機能をすべて利用できます。
{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *}
/// tip | 豆知識
コピペ用に手早く使いたい場合は、この例ではなく、下の最後の例を使ってください。
///
その後、その `Settings` クラスのインスタンス(この例では `settings` オブジェクトを作成すると、Pydantic は環境変数を大文字小文字を区別せずに読み取ります。つまり、大文字の `APP_NAME` という変数は、属性 `app_name` に対しても読み取られます。
次に、データが変換・バリデーションされます。したがって、`settings` オブジェクトを使うと、宣言した型のデータ(例: `items_per_user``int`)が得られます。
### `settings` の使用 { #use-the-settings }
次に、アプリケーションで新しい `settings` オブジェクトを使用できます:
{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *}
### サーバーを実行 { #run-the-server }
次に、設定を環境変数として渡してサーバーを実行します。たとえば、`ADMIN_EMAIL` と `APP_NAME` を次のように設定できます:
<div class="termy">
```console
$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
/// tip | 豆知識
1つのコマンドに複数の環境変数を設定するには、スペースで区切ってコマンドの前に並べます。
///
すると、`admin_email` の設定は `"deadpool@example.com"` に設定されます。
`app_name``"ChimichangApp"` になります。
`items_per_user` はデフォルト値の `50` のままです。
## 別モジュールでの設定 { #settings-in-another-module }
[大規模アプリケーション - 複数ファイル](../tutorial/bigger-applications.md){.internal-link target=_blank} で見たように、これらの設定を別のモジュールファイルに置くこともできます。
たとえば、`config.py` というファイルに次のように書けます:
{* ../../docs_src/settings/app01_py310/config.py *}
そして、`main.py` というファイルでそれを使います:
{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *}
/// tip | 豆知識
[大規模アプリケーション - 複数ファイル](../tutorial/bigger-applications.md){.internal-link target=_blank} で見たように、`__init__.py` ファイルも必要です。
///
## 依存関係での設定 { #settings-in-a-dependency }
場合によっては、どこでも使うグローバルな `settings` オブジェクトを持つ代わりに、依存関係から設定を提供すると便利なことがあります。
これは特にテスト時に有用で、依存関係を独自のカスタム設定で簡単にオーバーライドできるからです。
### 設定ファイル { #the-config-file }
前の例から続けると、`config.py` ファイルは次のようになります:
{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *}
ここでは、デフォルトのインスタンス `settings = Settings()` を作成していないことに注意してください。
### メインアプリファイル { #the-main-app-file }
ここでは、新しい `config.Settings()` を返す依存関係を作成します。
{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *}
/// tip | 豆知識
`@lru_cache` については後で説明します。
今は `get_settings()` が普通の関数だと考えてください。
///
そして、*path operation 関数*から依存関係として要求し、必要な場所でどこでも使えます。
{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *}
### 設定とテスト { #settings-and-testing }
次に、`get_settings` の依存関係オーバーライドを作ることで、テスト中に別の設定オブジェクトを提供するのがとても簡単になります:
{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *}
依存関係オーバーライドでは、新しい `Settings` オブジェクトを作る際に `admin_email` に新しい値を設定し、その新しいオブジェクトを返します。
そして、それが使用されていることをテストできます。
## `.env` ファイルの読み込み { #reading-a-env-file }
変更が多くなりそうな設定が多数ある場合、環境ごとにファイルに入れて、環境変数としてそこから読み込むと便利なことがあります。
このプラクティスは十分に一般的で名前もあり、これらの環境変数は通常 `.env` というファイルに置かれ、そのファイルは「dotenv」と呼ばれます。
/// tip | 豆知識
ドット(`.`で始まるファイルは、Linux や macOS のような Unix 系システムでは隠しファイルです。
ただし、dotenv ファイルは必ずしもその正確なファイル名である必要はありません。
///
Pydantic は外部ライブラリを使ってこの種のファイルからの読み込みをサポートしています。詳細は <a href="https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support" class="external-link" target="_blank">Pydantic Settings: Dotenv (.env) support</a> を参照してください。
/// tip | 豆知識
これを機能させるには、`pip install python-dotenv` が必要です。
///
### `.env` ファイル { #the-env-file }
次のような `.env` ファイルを用意できます:
```bash
ADMIN_EMAIL="deadpool@example.com"
APP_NAME="ChimichangApp"
```
### `.env` から設定を読む { #read-settings-from-env }
そして、`config.py` を次のように更新します:
{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *}
/// tip | 豆知識
`model_config` 属性は Pydantic の設定専用です。詳しくは <a href="https://docs.pydantic.dev/latest/concepts/config/" class="external-link" target="_blank">Pydantic: Concepts: Configuration</a> を参照してください。
///
ここでは、Pydantic の `Settings` クラス内で設定 `env_file` を定義し、使用したい dotenv ファイルのファイル名を指定しています。
### `lru_cache``Settings` を一度だけ作成 { #creating-the-settings-only-once-with-lru-cache }
ディスクからファイルを読むのは通常コスト遅延が高い処理なので、1回だけ実行して同じ設定オブジェクトを再利用し、各リクエストごとに読み直さないのが望ましいです。
しかし、次のようにするたびに:
```Python
Settings()
```
新しい `Settings` オブジェクトが作成され、その作成時に `.env` ファイルが再度読み込まれます。
依存関数が次のようであれば:
```Python
def get_settings():
return Settings()
```
各リクエストごとにそのオブジェクトを作成し、各リクエストごとに `.env` ファイルを読み込むことになります。⚠️
しかし、上に `@lru_cache` デコレータを使っているので、`Settings` オブジェクトは最初に呼び出されたときに一度だけ作成されます。✔️
{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *}
その後のリクエスト用の依存関係で `get_settings()` が呼ばれるたびに、`get_settings()` の内部コードを実行して新しい `Settings` オブジェクトを作るのではなく、最初の呼び出しで返されたのと同じオブジェクトを何度でも返します。
#### `lru_cache` の技術詳細 { #lru-cache-technical-details }
`@lru_cache` は、毎回関数のコードを実行して再計算するのではなく、最初に返した値を返すように、修飾する関数を変更します。
したがって、その下の関数は引数の組み合わせごとに一度だけ実行されます。そして、その各引数の組み合わせで返された値は、まったく同じ引数の組み合わせで呼び出されたときに何度でも再利用されます。
たとえば、次のような関数があるとします:
```Python
@lru_cache
def say_hi(name: str, salutation: str = "Ms."):
return f"Hello {salutation} {name}"
```
プログラムは次のように実行されます:
```mermaid
sequenceDiagram
participant code as Code
participant function as say_hi()
participant execute as Execute function
rect rgba(0, 255, 0, .1)
code ->> function: say_hi(name="Camila")
function ->> execute: execute function code
execute ->> code: return the result
end
rect rgba(0, 255, 255, .1)
code ->> function: say_hi(name="Camila")
function ->> code: return stored result
end
rect rgba(0, 255, 0, .1)
code ->> function: say_hi(name="Rick")
function ->> execute: execute function code
execute ->> code: return the result
end
rect rgba(0, 255, 0, .1)
code ->> function: say_hi(name="Rick", salutation="Mr.")
function ->> execute: execute function code
execute ->> code: return the result
end
rect rgba(0, 255, 255, .1)
code ->> function: say_hi(name="Rick")
function ->> code: return stored result
end
rect rgba(0, 255, 255, .1)
code ->> function: say_hi(name="Camila")
function ->> code: return stored result
end
```
今回の依存関数 `get_settings()` の場合、関数は引数を一切取りません。そのため、常に同じ値を返します。
この方法は、ほとんどグローバル変数のように振る舞います。しかし、依存関数を使っているので、テストのために簡単にオーバーライドできます。
`@lru_cache` は Python 標準ライブラリの `functools` の一部です。詳細は <a href="https://docs.python.org/3/library/functools.html#functools.lru_cache" class="external-link" target="_blank">Python の `@lru_cache` ドキュメント</a>を参照してください。
## まとめ { #recap }
Pydantic Settings を使うことで、アプリケーションの設定や構成を、Pydantic モデルの力を活かして扱えます。
* 依存関係を使うことで、テストを簡素化できます。
* `.env` ファイルを利用できます。
* `@lru_cache` を使うと、各リクエストごとに dotenv ファイルを繰り返し読み込むのを避けつつ、テスト時にはオーバーライドできます。

View File

@ -0,0 +1,67 @@
# サブアプリケーション - マウント { #sub-applications-mounts }
それぞれ独立した OpenAPI とドキュメント UI を持つ2つの独立した FastAPI アプリケーションが必要な場合、メインアプリに1つ以上のサブアプリケーションを「マウント」できます。
## FastAPI アプリケーションのマウント { #mounting-a-fastapi-application }
「マウント」とは、特定のパスに完全に「独立した」アプリケーションを追加し、そのサブアプリケーションで宣言された path operation によって、そのパス以下のすべてを処理させることを意味します。
### トップレベルアプリケーション { #top-level-application }
まず、メインのトップレベル **FastAPI** アプリケーションと、その path operation を作成します:
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *}
### サブアプリケーション { #sub-application }
次に、サブアプリケーションとその path operation を作成します。
このサブアプリケーションは通常の FastAPI アプリケーションですが、これを「マウント」します:
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *}
### サブアプリケーションをマウント { #mount-the-sub-application }
トップレベルのアプリケーション `app` に、サブアプリケーション `subapi` をマウントします。
この例では、パス `/subapi` にマウントされます:
{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *}
### 自動 API ドキュメントの確認 { #check-the-automatic-api-docs }
では、`fastapi` コマンドでこのファイルを実行します:
<div class="termy">
```console
$ fastapi dev main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
そして、<a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> を開きます。
メインアプリ用の自動 API ドキュメントが表示され、そのアプリ自身の path operation のみが含まれます:
<img src="/img/tutorial/sub-applications/image01.png">
次に、サブアプリケーションのドキュメント <a href="http://127.0.0.1:8000/subapi/docs" class="external-link" target="_blank">http://127.0.0.1:8000/subapi/docs</a> を開きます。
サブアプリケーション用の自動 API ドキュメントが表示され、そのアプリ自身の path operation のみが、正しいサブパス接頭辞 `/subapi` の下で表示されます:
<img src="/img/tutorial/sub-applications/image02.png">
どちらの UI でも操作すれば正しく動作します。ブラウザがそれぞれのアプリ/サブアプリと通信できるためです。
### 技術詳細: `root_path` { #technical-details-root-path }
上記のようにサブアプリケーションをマウントすると、FastAPI は ASGI 仕様の `root_path` と呼ばれる仕組みを使って、そのサブアプリケーションへのマウントパスを伝播します。
このため、サブアプリケーションはドキュメント UI でそのパス接頭辞を使用すべきことを認識できます。
さらに、サブアプリケーション自身が別のサブアプリケーションをマウントしていても問題ありません。FastAPI がこれらの `root_path` をすべて自動的に処理するためです。
`root_path` の詳細や明示的な指定方法については、[プロキシの背後で](behind-a-proxy.md){.internal-link target=_blank} の節で学べます。

View File

@ -0,0 +1,126 @@
# テンプレート { #templates }
**FastAPI** では任意のテンプレートエンジンを使用できます。
Flask などでも使われている Jinja2 が一般的な選択肢です。
Starlette によって提供され、**FastAPI** アプリで直接使える、簡単に設定できるユーティリティがあります。
## 依存関係のインストール { #install-dependencies }
[仮想環境](../virtual-environments.md){.internal-link target=_blank} を作成して有効化し、`jinja2` をインストールします:
<div class="termy">
```console
$ pip install jinja2
---> 100%
```
</div>
## `Jinja2Templates` の使用 { #using-jinja2templates }
* `Jinja2Templates` をインポートします。
* 後で再利用できる `templates` オブジェクトを作成します。
* テンプレートを返す path operation に `Request` パラメータを宣言します。
* 作成した `templates` を使って `TemplateResponse` をレンダリングして返します。テンプレート名、リクエストオブジェクト、Jinja2 テンプレート内で使用するキーと値のペアからなる "context" の辞書を渡します。
{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *}
/// note | 備考
FastAPI 0.108.0、Starlette 0.29.0 以前では、`name` は最初のパラメータでした。
またそれ以前のバージョンでは、`request` オブジェクトは Jinja2 用のコンテキスト内のキーと値のペアの一部として渡されていました。
///
/// tip | 豆知識
`response_class=HTMLResponse` を宣言すると、ドキュメント UI がレスポンスが HTML であることを認識できます。
///
/// note | 技術詳細
`from starlette.templating import Jinja2Templates` を使うこともできます。
**FastAPI** は、開発者であるあなたの利便性のために、`starlette.templating` と同じものを `fastapi.templating` として提供しています。しかし、利用可能なレスポンスのほとんどは Starlette から直接提供されています。`Request` や `StaticFiles` も同様です。
///
## テンプレートの作成 { #writing-templates }
例えば、`templates/item.html` に次のようなテンプレートを書きます:
```jinja hl_lines="7"
{!../../docs_src/templates/templates/item.html!}
```
### テンプレートのコンテキスト値 { #template-context-values }
次のような HTML 内で:
{% raw %}
```jinja
Item ID: {{ id }}
```
{% endraw %}
...渡した "context" の `dict` から取得した `id` が表示されます:
```Python
{"id": id}
```
例えば、ID が `42` の場合は次のようにレンダリングされます:
```html
Item ID: 42
```
### テンプレートの `url_for` の引数 { #template-url-for-arguments }
テンプレート内でも `url_for()` を使用できます。引数には、対応する path operation 関数で使われるのと同じ引数を取ります。
したがって、次の部分は:
{% raw %}
```jinja
<a href="{{ url_for('read_item', id=id) }}">
```
{% endraw %}
...path operation 関数 `read_item(id=id)` が処理するのと同じ URL へのリンクを生成します。
例えば、ID が `42` の場合は次のようにレンダリングされます:
```html
<a href="/items/42">
```
## テンプレートと静的ファイル { #templates-and-static-files }
テンプレート内で `url_for()` を使用し、例えば `name="static"` でマウントした `StaticFiles` に対して利用できます。
```jinja hl_lines="4"
{!../../docs_src/templates/templates/item.html!}
```
この例では、`static/styles.css` の CSS ファイルにリンクします:
```CSS hl_lines="4"
{!../../docs_src/templates/static/styles.css!}
```
また、`StaticFiles` を使用しているため、その CSS ファイルは **FastAPI** アプリケーションから URL `/static/styles.css` で自動的に配信されます。
## さらに詳しく { #more-details }
より詳しい内容(テンプレートのテスト方法など)については、<a href="https://www.starlette.dev/templates/" class="external-link" target="_blank">Starlette のテンプレートに関するドキュメント</a>を参照してください。

View File

@ -0,0 +1,53 @@
# 依存関係のオーバーライドによるテスト { #testing-dependencies-with-overrides }
## テスト時の依存関係のオーバーライド { #overriding-dependencies-during-testing }
テスト中に依存関係をオーバーライドしたい場面がいくつかあります。
元の依存関係(およびそれにぶら下がるサブ依存関係)を実行したくない場合です。
代わりに、テストの間だけ(特定のテストだけでも)使われる別の依存関係を提供し、元の依存関係の値が使われていた箇所で利用できる値を返したいのです。
### ユースケース: 外部サービス { #use-cases-external-service }
例として、呼び出す必要がある外部の認証プロバイダがあるとします。
トークンを送ると、認証済みユーザーが返ってきます。
このプロバイダはリクエストごとに課金されるかもしれず、テスト用に固定のモックユーザーを使う場合に比べて呼び出しに余分な時間がかかるかもしれません。
外部プロバイダ自体の動作は一度はテストしたいでしょうが、実行されるすべてのテストで毎回呼び出す必要はありません。
この場合、そのプロバイダを呼び出す依存関係をオーバーライドし、テストのときだけモックユーザーを返すカスタムの依存関係を使えます。
### app.dependency_overrides 属性を使う { #use-the-app-dependency-overrides-attribute }
このような場合のために、**FastAPI** アプリケーションには `app.dependency_overrides` という属性があり、これは単純な `dict` です。
テスト用に依存関係をオーバーライドするには、キーに元の依存関係(関数)を、値にオーバーライドする依存関係(別の関数)を設定します。
すると **FastAPI** は元の依存関係の代わりにそのオーバーライドを呼び出します。
{* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *}
/// tip | 豆知識
アプリケーション内のどこで使われている依存関係に対しても、依存関係のオーバーライドを設定できます。
元の依存関係は、*path operation 関数*、*path operation デコレータ*(戻り値を使わない場合)、`.include_router()` の呼び出しなど、さまざまな場所で使われていてもかまいません。
FastAPI はそれでもオーバーライドできます。
///
その後、`app.dependency_overrides` を空の `dict` に設定することで、オーバーライドをリセット(削除)できます:
```Python
app.dependency_overrides = {}
```
/// tip | 豆知識
一部のテストの間だけ依存関係をオーバーライドしたい場合は、テストの開始時(テスト関数内)にオーバーライドを設定し、終了時(テスト関数の末尾)にリセットするとよいです。
///

View File

@ -0,0 +1,11 @@
# イベントのテスト: lifespan と startup - shutdown { #testing-events-lifespan-and-startup-shutdown }
テストで `lifespan` を実行する必要がある場合は、`with` 文と併用して `TestClient` を使用できます:
{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *}
より詳しい内容は、[公式 Starlette ドキュメントの「テストでの lifespan の実行」](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) を参照してください。
非推奨の `startup` および `shutdown` イベントについては、次のように `TestClient` を使用できます:
{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *}

View File

@ -0,0 +1,13 @@
# WebSocket のテスト { #testing-websockets }
WebSocket をテストするのにも同じ `TestClient` を使用できます。
そのために、`with` 文の中で `TestClient` を使用し、WebSocket に接続します:
{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *}
/// note | 備考
詳細については、Starlette のドキュメント「<a href="https://www.starlette.dev/testclient/#testing-websocket-sessions" class="external-link" target="_blank">WebSocket のテスト</a>」を参照してください。
///

View File

@ -0,0 +1,56 @@
# Request を直接使う { #using-the-request-directly }
これまで、必要なリクエストの各部分を、その型とともに宣言してきました。
次の場所からデータを取得します:
- パスのパラメータ
- ヘッダー
- クッキー
- など
こうすることで、**FastAPI** はそのデータを検証し、変換し、API のドキュメントを自動生成します。
しかし、`Request` オブジェクトに直接アクセスする必要がある場面もあります。
## `Request` オブジェクトの詳細 { #details-about-the-request-object }
**FastAPI** は内部的には **Starlette** の上にいくつかのツール層を載せたものなので、必要に応じて Starlette の <a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">`Request`</a> オブジェクトを直接使えます。
また、`Request` オブジェクトから直接データ(例: ボディ)を取得する場合、そのデータは FastAPI によって検証・変換・ドキュメント化OpenAPI による自動 API ユーザーインターフェース向け)されません。
ただし、通常どおりに宣言された他のパラメータ(例: Pydantic モデルのボディ)は引き続き検証・変換・注釈付けなどが行われます。
それでも、`Request` オブジェクトを取得するのが有用な特定のケースがあります。
## `Request` オブジェクトを直接使う { #use-the-request-object-directly }
たとえば、path operation 関数内でクライアントの IP アドレス/ホストを取得したいとします。
そのためには、リクエストに直接アクセスする必要があります。
{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *}
path operation 関数の引数として `Request` 型のパラメータを宣言すると、**FastAPI** はその引数に `Request` を渡します。
/// tip | 豆知識
この例では、`Request` 型の引数に加えて、パスパラメータも宣言しています。
そのため、パスパラメータは取り出され、検証され、指定した型に変換され、OpenAPI で注釈(ドキュメント化)されます。
同様に、通常どおり任意の他のパラメータを宣言しつつ、追加で `Request` も受け取れます。
///
## `Request` のドキュメント { #request-documentation }
より詳しくは、<a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">公式 Starlette ドキュメントサイトの `Request` オブジェクト</a>を参照してください。
/// note | 技術詳細
`from starlette.requests import Request` を使うこともできます。
**FastAPI** は開発者である皆さんの便宜のために直接提供していますが、これは Starlette からそのまま提供されているものです。
///

View File

@ -38,13 +38,13 @@ $ pip install websockets
しかし、これはWebSocketsのサーバーサイドに焦点を当て、動作する例を示す最も簡単な方法です。
{* ../../docs_src/websockets/tutorial001_py39.py hl[2,6:38,41:43] *}
{* ../../docs_src/websockets/tutorial001_py310.py hl[2,6:38,41:43] *}
## `websocket` を作成する { #create-a-websocket }
**FastAPI** アプリケーションで、`websocket` を作成します。
{* ../../docs_src/websockets/tutorial001_py39.py hl[1,46:47] *}
{* ../../docs_src/websockets/tutorial001_py310.py hl[1,46:47] *}
/// note | 技術詳細
@ -58,7 +58,7 @@ $ pip install websockets
WebSocketルートでは、メッセージを待機して送信するために `await` を使用できます。
{* ../../docs_src/websockets/tutorial001_py39.py hl[48:52] *}
{* ../../docs_src/websockets/tutorial001_py310.py hl[48:52] *}
バイナリやテキストデータ、JSONデータを送受信できます。
@ -154,7 +154,7 @@ $ fastapi dev main.py
WebSocket接続が閉じられると、 `await websocket.receive_text()` は例外 `WebSocketDisconnect` を発生させ、この例のようにキャッチして処理することができます。
{* ../../docs_src/websockets/tutorial003_py39.py hl[79:81] *}
{* ../../docs_src/websockets/tutorial003_py310.py hl[79:81] *}
試してみるには、

View File

@ -0,0 +1,51 @@
# WSGI の組み込み - Flask、Django など { #including-wsgi-flask-django-others }
[サブアプリケーション - マウント](sub-applications.md){.internal-link target=_blank}、[プロキシの背後](behind-a-proxy.md){.internal-link target=_blank} で見たように、WSGI アプリケーションをマウントできます。
そのために `WSGIMiddleware` を使用して、Flask や Django などの WSGI アプリをラップできます。
## `WSGIMiddleware` の使用 { #using-wsgimiddleware }
/// info | 情報
これには `a2wsgi` のインストールが必要です。例: `pip install a2wsgi`
///
`a2wsgi` から `WSGIMiddleware` をインポートします。
次に、そのミドルウェアで WSGI例: Flaskアプリをラップします。
そして、それをあるパスの下にマウントします。
{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *}
/// note | 備考
以前は `fastapi.middleware.wsgi``WSGIMiddleware` を使用することが推奨されていましたが、現在は非推奨です。
代わりに `a2wsgi` パッケージを使用することを推奨します。使い方は同じです。
`a2wsgi` パッケージがインストールされていることを確認し、`a2wsgi` から `WSGIMiddleware` を正しくインポートしてください。
///
## チェック { #check-it }
これで、パス `/v1/` 配下へのすべてのリクエストは Flask アプリケーションが処理します。
それ以外は **FastAPI** が処理します。
実行して <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a> にアクセスすると、Flask からのレスポンスが表示されます:
```txt
Hello, World from Flask!
```
さらに <a href="http://localhost:8000/v2" class="external-link" target="_blank">http://localhost:8000/v2</a> にアクセスすると、FastAPI からのレスポンスが表示されます:
```JSON
{
"message": "Hello World"
}
```

View File

@ -1,8 +1,8 @@
# 代替ツールから受けたインスピレーションと比較
# 代替ツールから受けたインスピレーションと比較 { #alternatives-inspiration-and-comparisons }
何が**FastAPI**にインスピレーションを与えたのか、他の代替ツールと比較してどうか、そしてそこから何を学んだのかについて。
## はじめに
## はじめに { #intro }
**FastAPI**は、代替ツールのこれまでの働きがなければ存在しなかったでしょう。
@ -12,17 +12,17 @@
しかし、その時点では、これらの機能をすべて提供し、以前のツールから優れたアイデアを取り入れ、可能な限り最高の方法でそれらを組み合わせ、それまで利用できなかった言語機能 (Python 3.6以降の型ヒント) を利用したものを作る以外に選択肢はありませんでした。
## 以前のツール
## 以前のツール { #previous-tools }
### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a>
### <a href="https://www.djangoproject.com/" class="external-link" target="_blank">Django</a> { #django }
Pythonのフレームワークの中で最もポピュラーで、広く信頼されています。Instagramのようなシステムの構築に使われています。
リレーショナルデータベース (MySQLやPostgreSQLなど) と比較的強固に結合されているので、NoSQLデータベース (Couchbase、MongoDB、Cassandraなど) をメインに利用することは簡単ではありません。
バックエンドでHTMLを生成するために作られたものであり、現代的なフロントエンド (ReactやVue.js、Angularなど) や、他のシステム (IoTデバイスなど) と通信するAPIを構築するために作られたものではありません。
バックエンドでHTMLを生成するために作られたものであり、現代的なフロントエンド (ReactやVue.js、Angularなど) や、他のシステム (<abbr title="Internet of Things - モノのインターネット">IoT</abbr>デバイスなど) と通信するAPIを構築するために作られたものではありません。
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a>
### <a href="https://www.django-rest-framework.org/" class="external-link" target="_blank">Django REST Framework</a> { #django-rest-framework }
Django REST Frameworkは、Djangoを下敷きにしてWeb APIを構築する柔軟なツールキットとして、APIの機能を向上させるために作られました。
@ -42,7 +42,7 @@ Django REST Framework は Tom Christie によって作成されました。Starl
///
### <a href="http://flask.pocoo.org/" class="external-link" target="_blank">Flask</a>
### <a href="https://flask.palletsprojects.com" class="external-link" target="_blank">Flask</a> { #flask }
Flask は「マイクロフレームワーク」であり、データベースとの統合のようなDjangoがデフォルトで持つ多くの機能は含まれていません。
@ -64,7 +64,7 @@ Flaskのシンプルさを考えると、APIを構築するのに適している
///
### <a href="http://docs.python-requests.org" class="external-link" target="_blank">Requests</a>
### <a href="https://requests.readthedocs.io" class="external-link" target="_blank">Requests</a> { #requests }
**FastAPI**は実際には**Requests**の代替ではありません。それらのスコープは大きく異なります。
@ -80,7 +80,7 @@ Requestsは非常にシンプルかつ直感的なデザインで使いやすく
公式サイトで以下のように言われているのは、それが理由です。
> Requestsは今までで最もダウンロードされたPythonパッケージである
> Requestsは史上最もダウンロードされたPythonパッケージのひとつです
使い方はとても簡単です。例えば、`GET`リクエストを実行するには、このように書けば良いです:
@ -88,7 +88,7 @@ Requestsは非常にシンプルかつ直感的なデザインで使いやすく
response = requests.get("http://example.com/some/url")
```
対応するFastAPIのパスオペレーションはこのようになります:
対応するFastAPIのAPIのpath operationはこのようになります:
```Python hl_lines="1"
@app.get("/some/url")
@ -106,7 +106,7 @@ def read_url():
///
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a>
### <a href="https://swagger.io/" class="external-link" target="_blank">Swagger</a> / <a href="https://github.com/OAI/OpenAPI-Specification/" class="external-link" target="_blank">OpenAPI</a> { #swagger-openapi }
私がDjango REST Frameworkに求めていた主な機能は、APIの自動的なドキュメント生成でした。
@ -131,13 +131,13 @@ def read_url():
///
### Flask REST フレームワーク
### Flask REST フレームワーク { #flask-rest-frameworks }
いくつかのFlask RESTフレームワークがありますが、それらを調査してみたところ、多くのものが不適切な問題が残ったまま、中断されたり放置されていることがわかりました。
### <a href="https://marshmallow.readthedocs.io/en/3.0/" class="external-link" target="_blank">Marshmallow</a>
### <a href="https://marshmallow.readthedocs.io/en/stable/" class="external-link" target="_blank">Marshmallow</a> { #marshmallow }
APIシステムで必要とされる主な機能の一つに、コード (Python) からデータを取り出して、ネットワークを介して送れるものに変換するデータの「<abbr title="marshalling, conversion">シリアライゼーション</abbr>」があります。例えば、データベースのデータを含むオブジェクトをJSONオブジェクトに変換したり、`datetime` オブジェクトを文字列に変換するなどです。
APIシステムで必要とされる主な機能の一つに、コード (Python) からデータを取り出して、ネットワークを介して送れるものに変換するデータの「<dfn title="別名: marshalling、変換">シリアライゼーション</dfn>」があります。例えば、データベースのデータを含むオブジェクトをJSONオブジェクトに変換したり、`datetime` オブジェクトを文字列に変換するなどです。
APIが必要とするもう一つの大きな機能はデータのバリデーションであり、特定のパラメータが与えられた場合にデータが有効であることを確認することです。例えば、あるフィールドがランダムな文字列ではなく `int` であることなどです。これは特に受信するデータに対して便利です。
@ -145,7 +145,7 @@ APIが必要とするもう一つの大きな機能はデータのバリデー
これらの機能は、Marshmallowが提供するものです。Marshmallowは素晴らしいライブラリで、私も以前に何度も使ったことがあります。
しかし、それはPythonの型ヒントが存在する前に作られたものです。そのため、すべての<abbr title="データがどのように形成されるべきかの定義">スキーマ</abbr>を定義するためには、Marshmallowが提供する特定のユーティリティやクラスを使用する必要があります。
しかし、それはPythonの型ヒントが存在する前に作られたものです。そのため、すべての<dfn title="データがどのように構成されるべきかの定義">スキーマ</dfn>を定義するためには、Marshmallowが提供する特定のユーティリティやクラスを使用する必要があります。
/// check | **FastAPI**へ与えたインスピレーション
@ -153,9 +153,9 @@ APIが必要とするもう一つの大きな機能はデータのバリデー
///
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a>
### <a href="https://webargs.readthedocs.io/en/latest/" class="external-link" target="_blank">Webargs</a> { #webargs }
APIに求められる他の大きな機能として、<abbr title="Pythonデータの読み込みと変換">受信したリクエストデータのパース</abbr>があります。
APIに求められる他の大きな機能として、<dfn title="Pythonデータの読み込みと変換">受信したリクエストデータのパース</dfn>があります。
WebargsはFlaskをはじめとするいくつかのフレームワークの上にそれを提供するために作られたツールです。
@ -175,7 +175,7 @@ Webargsは、Marshmallowと同じ開発者により作られました。
///
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a>
### <a href="https://apispec.readthedocs.io/en/stable/" class="external-link" target="_blank">APISpec</a> { #apispec }
MarshmallowとWebargsはバリデーション、パース、シリアライゼーションをプラグインとして提供しています。
@ -205,7 +205,7 @@ OpenAPIという、APIについてのオープンな標準をサポートして
///
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a>
### <a href="https://flask-apispec.readthedocs.io/en/latest/" class="external-link" target="_blank">Flask-apispec</a> { #flask-apispec }
Webargs、Marshmallow、APISpecを連携させたFlaskプラグインです。
@ -237,7 +237,7 @@ Flask-apispecはMarshmallowと同じ開発者により作成されました。
///
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (と<a href="https://angular.io/" class="external-link" target="_blank">Angular</a>)
### <a href="https://nestjs.com/" class="external-link" target="_blank">NestJS</a> (と<a href="https://angular.io/" class="external-link" target="_blank">Angular</a>) { #nestjs-and-angular }
NestJSはAngularにインスパイアされたJavaScript (TypeScript) NodeJSフレームワークで、Pythonですらありません。
@ -259,13 +259,13 @@ Angular 2にインスピレーションを受けた、統合された依存性
///
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a>
### <a href="https://sanic.readthedocs.io/en/latest/" class="external-link" target="_blank">Sanic</a> { #sanic }
`asyncio`に基づいた、Pythonのフレームワークの中でも非常に高速なものの一つです。Flaskと非常に似た作りになっています。
/// note | 技術詳細
Pythonの`asyncio`ループの代わりに、`uvloop`が利用されています。それにより、非常に高速です。
Pythonの`asyncio`ループの代わりに、<a href="https://github.com/MagicStack/uvloop" class="external-link" target="_blank">`uvloop`</a>が利用されています。それにより、非常に高速です。
`Uvicorn`と`Starlette`に明らかなインスピレーションを与えており、それらは現在オープンなベンチマークにおいてSanicより高速です。
@ -279,12 +279,10 @@ Pythonの`asyncio`ループの代わりに、`uvloop`が利用されています
///
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a>
### <a href="https://falconframework.org/" class="external-link" target="_blank">Falcon</a> { #falcon }
Falconはもう一つの高性能Pythonフレームワークで、ミニマムに設計されており、Hugのような他のフレームワークの基盤として動作します。
Pythonのウェブフレームワーク標準規格 (WSGI) を使用していますが、それは同期的であるためWebSocketなどの利用には対応していません。とはいえ、それでも非常に高い性能を持っています。
これは、「リクエスト」と「レスポンス」の2つのパラメータを受け取る関数を持つように設計されています。そして、リクエストからデータを「読み込み」、レスポンスにデータを「書き込み」ます。この設計のため、Python標準の型ヒントでリクエストのパラメータやボディを関数の引数として宣言することはできません。
そのため、データのバリデーション、シリアライゼーション、ドキュメント化は、自動的にできずコードの中で行わなければなりません。あるいは、HugのようにFalconの上にフレームワークとして実装されなければなりません。このような分断は、パラメータとして1つのリクエストオブジェクトと1つのレスポンスオブジェクトを持つというFalconのデザインにインスピレーションを受けた他のフレームワークでも起こります。
@ -299,7 +297,7 @@ Hug (HugはFalconをベースにしています) と一緒に、**FastAPI**が`r
///
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a>
### <a href="https://moltenframework.com/" class="external-link" target="_blank">Molten</a> { #molten }
**FastAPI**を構築する最初の段階でMoltenを発見しました。そして、それは非常に似たようなアイデアを持っています。
@ -323,7 +321,7 @@ Pydanticのようなデータのバリデーション、シリアライゼーシ
///
### <a href="http://www.hug.rest/" class="external-link" target="_blank">Hug</a>
### <a href="https://github.com/hugapi/hug" class="external-link" target="_blank">Hug</a> { #hug }
Hugは、Pythonの型ヒントを利用してAPIパラメータの型宣言を実装した最初のフレームワークの1つです。これは素晴らしいアイデアで、他のツールが同じことをするきっかけとなりました。
@ -353,7 +351,7 @@ Hugは、**FastAPI**がヘッダーやクッキーを設定するために関数
///
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5)
### <a href="https://github.com/encode/apistar" class="external-link" target="_blank">APIStar</a> (<= 0.5) { #apistar-0-5 }
**FastAPI**を構築することを決める直前に、**APIStar**サーバーを見つけました。それは私が探していたものがほぼすべて含まれており、素晴らしいデザインでした。
@ -401,9 +399,9 @@ APIStarはTom Christieにより開発されました。以下の開発者でも
///
## **FastAPI**が利用しているもの
## **FastAPI**が利用しているもの { #used-by-fastapi }
### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a>
### <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> { #pydantic }
Pydanticは、Pythonの型ヒントを元にデータのバリデーション、シリアライゼーション、 (JSON Schemaを使用した) ドキュメントを定義するライブラリです。
@ -419,9 +417,9 @@ Marshmallowに匹敵しますが、ベンチマークではMarshmallowよりも
///
### <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a>
### <a href="https://www.starlette.dev/" class="external-link" target="_blank">Starlette</a> { #starlette }
Starletteは、軽量な<abbr title="非同期Python webを構築するための新標準">ASGI</abbr>フレームワーク/ツールキットで、高性能な非同期サービスの構築に最適です。
Starletteは、軽量な<dfn title="非同期Python Webアプリケーションを構築するための新しい標準">ASGI</dfn>フレームワーク/ツールキットで、高性能な非同期サービスの構築に最適です。
非常にシンプルで直感的です。簡単に拡張できるように設計されており、モジュール化されたコンポーネントを持っています。
@ -429,15 +427,14 @@ Starletteは、軽量な<abbr title="非同期Python webを構築するための
* 非常に感動的な性能。
* WebSocketのサポート。
* GraphQLのサポート。
* インプロセスのバックグラウンドタスク。
* 起動およびシャットダウンイベント。
* requestsに基づいて構築されたテストクライアント。
* HTTPXに基づいて構築されたテストクライアント。
* CORS、GZip、静的ファイル、ストリーミング応答。
* セッションとクッキーのサポート。
* 100%のテストカバレッジ。
* 100%の型注釈付きコードベース。
* ハードな依存関係はない。
* ハードな依存関係はない。
Starletteは、現在テストされているPythonフレームワークの中で最も速いフレームワークです。フレームワークではなくサーバーであるUvicornだけが上回っています。
@ -465,7 +462,7 @@ webに関するコアな部分を全て扱います。その上に機能を追
///
### <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a>
### <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a> { #uvicorn }
Uvicornは非常に高速なASGIサーバーで、uvloopとhttptoolsにより構成されています。
@ -477,12 +474,12 @@ Starletteや**FastAPI**のサーバーとして推奨されています。
**FastAPI**アプリケーションを実行するメインのウェブサーバーである点。
Gunicornと組み合わせることで、非同期でマルチプロセスなサーバーを持つことがきます。
コマンドラインオプション `--workers` を使って、非同期のマルチプロセスサーバーにできます。
詳細は[デプロイ](deployment/index.md){.internal-link target=_blank}の項目で確認してください。
///
## ベンチマーク と スピード
## ベンチマーク と スピード { #benchmarks-and-speed }
Uvicorn、Starlette、FastAPIの違いを理解、比較、確認するには、[ベンチマーク](benchmarks.md){.internal-link target=_blank}を確認してください。

View File

@ -1,18 +1,18 @@
# 並行処理と async / await
# 並行処理と async / await { #concurrency-and-async-await }
*path operation 関数*のための `async def` に関する詳細と非同期 (asynchronous) コード、並行処理 (Concurrency)、そして、並列処理 (Parallelism) の背景について。
*path operation 関数*のための `async def` 構文に関する詳細と非同期コード、並行処理、並列処理の背景についてです
## 急いでいますか?
## 急いでいますか? { #in-a-hurry }
<abbr title="too long; didn't read (長すぎて読めない人のための要約という意味のスラング)"><strong>TL;DR:</strong></abbr>
<abbr title="too long; didn't read - 長すぎて読まなかった"><strong>TL;DR:</strong></abbr>
次のような、`await` を使用して呼び出すべきサードパーティライブラリを使用している場合:
次のよう`await` で呼び出すよう指示されているサードパーティライブラリを使っているなら:
```Python
results = await some_library()
```
以下の様に `async def` を使用して*path operation 関数*を宣言します。
*path operation 関数*は次のように `async def` で宣言します:
```Python hl_lines="2"
@app.get('/')
@ -23,13 +23,13 @@ async def read_results():
/// note | 備考
`async def` を使用して作成された関数の内部でしか `await` は使用できません。
`await` は `async def` で作られた関数の内部でしか使えません。
///
---
データベース、API、ファイルシステムなどと通信し、`await` の使用をサポートしていないサードパーティライブラリ (現在のほとんどのデータベースライブラリに当てはまります) を使用している場合、次の様に、単に `def` を使用して通常通り *path operation 関数*宣言してください:
データベース、API、ファイルシステムなどと通信しつつ `await` の使用をサポートしていないサードパーティライブラリ (現在のところ多くのデータベースライブラリが該当します) を使っている場合、*path operation 関数*は通常どおり `def`宣言してください:
```Python hl_lines="2"
@app.get('/')
@ -40,272 +40,307 @@ def results():
---
アプリケーションが (どういうわけか) 他の何とも通信せず、応答を待つ必要がない場合は、`async def` を使用して下さい。
アプリケーションが (何らかの理由で) ほかの何とも通信せず応答を待つ必要がないなら、`await` を内部で使わなくても `async def` を使ってください。
---
よく分からない場合は、通常の `def` を使用して下さい。
よく分からない場合は、通常の `def` を使ってください。
---
**備考**: *path operation 関数*に必要なだけ `def``async def` を混在させ、それぞれに最適なオプションを使用して定義できます。それに応じてFastAPIは正しい処理を行います。
**備考**: 必要に応じて *path operation 関数* では `def``async def` を混在させ、それぞれに最適な選択肢で定義できます。FastAPI は適切に処理します。
とにかく、上記のいずれの場合でもFastAPIは非同期で動作し非常に高速です。
いずれの場合でもFastAPI は非同期で動作し非常に高速です。
しかし、上記のステップに従うことで、パフォーマンスの最適化を行えます。
ただし上記の手順に従うことで、さらにパフォーマンス最適化が可能になります。
## 技術詳細
## 技術詳細 { #technical-details }
現代版のPythonは「**非同期コード**」を、「**コルーチン**」と称されるものを利用してサポートしています。これは **`async``await`** 構文を用います。
モダンな Python は **「非同期コード」** を **「コルーチン」** と呼ばれる仕組みでサポートしており、構文は **`async``await`** です。
次のセクションで、フレーズ内のパーツを順に見ていきましょう:
以下のセクションで、このフレーズをパーツごとに見ていきます:
* **非同期コード**
* **`async``await`**
* **コルーチン**
## 非同期コード
## 非同期コード { #asynchronous-code }
非同期コードとは、言語💬がコード内のどこかで、コンピュータ/プログラム🤖に *他の何か* がどこか別の箇所で終了するのを待つように伝える手段を持っていることを意味します。*他の何か* は「遅いファイル📝」と呼ばれているとしましょう.
非同期コードとは、言語 💬 がコードのどこかの時点で、コンピュータ/プログラム 🤖 に「どこか別のところで終わるまで、別の何か」を待つ必要があると伝える手段を持っている、ということです。その「別の何か」を「遅いファイル」📝 と呼ぶことにしましょう。
したがって、コンピュータは「遅いファイル📝」が終了するまで、他の処理ができます。
その間、コンピュータは「遅いファイル」📝 が終わるまで、他の作業を進められます。
コンピュータ/プログラム🤖は再び待機する機会があるときや、その時点で行っていたすべての作業が完了するたびに戻ってきます。そして、必要な処理をしながら、コンピュータ/プログラム🤖が待っていた処理のどれかが終わっているかどうか確認します。
その後、コンピュータ/プログラム 🤖 は、また待つ機会が来たときや、その時点で抱えていた作業をすべて終えたときに戻ってきます。そして、待っていたタスクのどれかが終わっていないか確認し、必要な処理を実行します。
次に、それ🤖が最初のタスク (要するに、先程の「遅いファイル📝」)を終わらせて、そのタスクの結果を使う必要がある処理を続けます。
次に、最初に終わったタスク (たとえば「遅いファイル」📝) を取り、続きの処理を行います。
この「他の何かを待つ」とは、通常以下の様なものを待つような (プロセッサとRAMメモリの速度に比べて) 相対的に「遅い」<abbr title="インプットとアウトプット">I/O</abbr> 操作を指します:
この「別の何かを待つ」は、通常 <abbr title="Input and Output - 入出力">I/O</abbr> 操作を指し、(プロセッサや RAM の速度に比べて) 相対的に「遅い」待機を伴いす。例えば次のようなものです:
* ネットワーク経由でクライアントから送信されるデータ
* ネットワーク経由でクライアントが受信する、プログラムから送信されたデータ
* システムによって読み取られ、プログラムに渡されるディスク内のファイル内容
* プログラムがシステムに渡して、ディスクに書き込む内容
* リモートAPI操作
* クライアントからネットワーク経由でデータが送られてくるのを待つ
* プログラムが送信したデータをクライアントがネットワーク経由で受け取るのを待つ
* ディスク上のファイル内容がシステムにより読み取られ、プログラムに渡されるのを待つ
* プログラムがシステムに渡した内容がディスクに書き込まれるのを待つ
* リモート API 操作
* データベース操作の完了
* データベースクエリが結果を返すこと
* など
* データベースクエリが結果を返すのを待つ
* など
実行時間のほとんどが<abbr title="インプットとアウトプット">I/O</abbr> 操作の待ち時間が占めるため、このような操作を「I/O バウンド」操作と言います。
実行時間の大半が <abbr title="Input and Output - 入出力">I/O</abbr> 操作の待ち時間に費やされるため、これらは「I/O バウンド」な操作と呼ばれます。
コンピュータ/プログラムがこのような遅いタスクと「同期 (タスクの結果を取得して作業を続行するために、何もせずに、タスクが完了する瞬間を正確に待つ)」する必要がないため、「非同期」と呼ばれます
「非同期」と呼ばれるのは、コンピュータ/プログラムがその遅いタスクと「同期」(タスクがちょうど終わる瞬間を、何もせずに待つ) する必要がないからです。結果を受け取って処理を続けるために、空待ちする必要がありません
その代わりに、「非同期」システムであることにより、いったん終了すると、タスクは、コンピュータ/プログラムが既に開始した処理がすべて完了するのをほんの少し (数マイクロ秒) 待って、結果を受け取りに戻ってきます。そして、処理を継続します。
代わりに「非同期」システムでは、タスクが終わったら、コンピュータ/プログラムが取りかかっている作業が終わるまで (数マイクロ秒ほど) 少し待ち、結果を受け取りに戻って処理を続けられます。
同期」の場合 (「非同期」とは異なり)、「シーケンシャル」という用語もよく使用されます。これは、コンピュータ/プログラムがすべてのステップを (待機が伴う場合でも別のタスクに切り替えることなく) 順番に実行するためです。
非同期」と対になる「同期」は、「シーケンシャル」と呼ばれることもあります。待機が含まれていても、別のタスクに切り替える前にコンピュータ/プログラムが手順を順番に実行するためです。
### 並行処理とハンバーガー
### 並行処理とハンバーガー { #concurrency-and-burgers }
記の**非同期**コードのアイデアは、**「並行処理」**と呼ばれることもあります。 **「並列処理」**とは異なります。
で説明した**非同期**コードの考え方は、**「並行処理」** と呼ばれることもあります。これは **「並列処理」** とは異なります。
**並行処理**と**並列処理**はどちらも「多かれ少なかれ同時に発生するさまざまなこと」に関連しています。
**並行処理****並列処理** も、「複数のことがだいたい同時に起きる」ことに関係します。
ただし、*並行処理*と*並列処理*の詳細はまったく異なります。
ただし、*並行処理**並列処理* の詳細はかなり異なります。
違いを確認するには、ハンバーガーに関する次の物語を想像してみてください:
違いを見るために、ハンバーガーに関する次の物語を想像してみてください。
### 並行ハンバーガー
### 並行ハンバーガー { #concurrent-burgers }
ファストフード🍔を食べようと、好きな人😍とレジに並んでおり、レジ係💁があなたの前にいる人達の注文を受けつけています。
あなたは好きな人とファストフードを買いに行き、前の人たちの注文をレジ係が受ける間、列に並びます。😍
それからあなたの番になり、好きな人😍と自分のために、2つの非常に豪華なハンバーガー🍔を注文します。
<img src="/img/async/concurrent-burgers/concurrent-burgers-01.png" class="illustration">
料金を支払います💸。
やがてあなたの番になり、好きな人と自分のために、とても豪華なハンバーガーを2つ注文します。🍔🍔
レジ係💁はキッチンの男👨‍🍳に向かって、あなたのハンバーガー🍔を準備しなければならないと伝えるために何か言いました (彼は現在、前のお客さんの商品を準備していますが)。
<img src="/img/async/concurrent-burgers/concurrent-burgers-02.png" class="illustration">
レジ係💁はあなたに番号札を渡します
レジ係はキッチンの料理人に、あなたのハンバーガーを用意するよう声をかけます (料理人はいま前のお客さんの分を作っています)
待っている間、好きな人😍と一緒にテーブルを選んで座り、好きな人😍と長い間話をします (注文したハンバーガーは非常に豪華で、準備に少し時間がかかるので✨🍔✨)。
<img src="/img/async/concurrent-burgers/concurrent-burgers-03.png" class="illustration">
ハンバーガー🍔を待ちながら好きな人😍とテーブルに座っている間、あなたの好きな人がなんて素晴らしく、かわいくて頭がいいんだと✨😍✨惚れ惚れしながら時間を費やすことができます。
支払いをします。💸
好きな人😍と話しながら待っている間、ときどき、カウンターに表示されている番号をチェックして、自分の番かどうかを確認します。
レジ係はあなたに番号札を渡します。
その後、ついにあなたの番になりました。カウンターに行き、ハンバーガー🍔を手に入れてテーブルに戻ります。
<img src="/img/async/concurrent-burgers/concurrent-burgers-04.png" class="illustration">
あなたとあなたの好きな人😍はハンバーガー🍔を食べて、楽しい時間を過ごします✨。
待っている間、好きな人とテーブルに移動して座り、(豪華なハンバーガーは時間がかかるので) しばらく話します。
テーブルで待っている間、好きな人がどれだけ素敵で、かわいくて、頭が良いかを眺めて時間を過ごせます ✨😍✨。
<img src="/img/async/concurrent-burgers/concurrent-burgers-05.png" class="illustration">
時々カウンターの表示を見て、自分の番号になっているか確認します。
やがてあなたの番になります。カウンターに行き、ハンバーガーを受け取り、テーブルに戻ります。
<img src="/img/async/concurrent-burgers/concurrent-burgers-06.png" class="illustration">
あなたと好きな人はハンバーガーを食べて、楽しい時間を過ごします。✨
<img src="/img/async/concurrent-burgers/concurrent-burgers-07.png" class="illustration">
/// info | 情報
美しいイラストは <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a> によるものです。🎨
///
---
上記のストーリーで、あなたがコンピュータ/プログラム🤖だと想像してみてください。
この物語で、あなた自身がコンピュータ/プログラム 🤖 だと想像してみてください。
列にいる間、あなたはアイドル状態です😴。何も「生産的」なことをせず、ただ自分の番を待っています。しかし、レジ係💁は注文を受け取るだけなので (商品の準備をしているわけではない)、列は高速です。したがって、何も問題ありません。
列にいる間は、何も「生産的」なことをせず、自分の番を待つだけのアイドル状態 😴 です。ただしレジ係は注文を取るだけ (作りはしない) なので列は速く進み、問題ありません。
それから、あなたの番になったら、実に「生産的な」作業を行います🤓、メニューを確認し、欲しいものを決め、好きな人😍の欲しいものを聞き、料金を支払い💸、現金またはカードを正しく渡したか確認し、正しく清算されたことを確認し、注文が正しく通っているかなどを確認します。
あなたの番になると、実際に「生産的」な作業をします。メニューを見て注文を決め、好きな人の分も確認し、支払い、正しい紙幣/カードを渡したか、正しく決済されたか、注文内容が正しいかなどを確認します。
しかし、ハンバーガー🍔をまだできていないので、ハンバーガーの準備ができるまで待機🕙する必要があるため、レジ係💁との作業は「一時停止⏸」になります。
しかし、ハンバーガーはまだ出来上がっていないので、レジ係とのやり取りは「一時停止」⏸ になります。ハンバーガーができるまで待つ 🕙 必要があるからです。
しかし、カウンターから離れて、番号札を持ってテーブルに座っているときは、注意を好きな人😍に切り替えて🔀、その上で「仕事⏯🤓」を行なえます。その後、好きな人😍といちゃつくかのような、非常に「生産的な🤓」ことを再び行います。
ただし、番号札を持ってカウンターから離れテーブルに座れば、注意を好きな人に切り替え 🔀、「その作業」⏯ 🤓 に取り組めます。好きな人といちゃつくという、とても「生産的」🤓 なことがまたできます。
次に、レジ係💁は、「ハンバーガーの準備ができました🍔」と言って、カウンターのディスプレイに番号を表示しますが、表示番号があなたの番号に変わっても、すぐに狂ったように飛んで行くようなことはありません。あなたは自分の番号札を持っていって、他の人も自分の番号札があるので、あなたのハンバーガー🍔を盗む人がいないことは知っています。
レジ係 💁 がカウンターの表示にあなたの番号を出して「ハンバーガーができました」と知らせても、あなたは表示が切り替わった瞬間に飛び跳ねたりしません。自分の番号札があり、他の人にもそれぞれ番号札があるので、ハンバーガーを盗られることはないと知っているからです。
なので、あなたは好きな人😍が話し終えるのを待って (現在の仕事⏯ / 処理中のタスクを終了します🤓)、優しく微笑んで、ハンバーガーを貰ってくるねと言います⏸。
だから、好きな人の話が終わるのを待ち (現在の作業 ⏯ / 処理中のタスクを完了し 🤓)、微笑んで「ハンバーガー取ってくるね」と言います ⏸。
次に、カウンターへ、いまから完了する最初のタスク⏯へ向かい、ハンバーガー🍔を受け取り、感謝の意を表して、テーブルに持っていきます。これで、カウンターとのやり取りのステップ/タスクが完了しました⏹。これにより、「ハンバーガーを食べる🔀⏯」という新しいタスクが作成されます。しかし、前の「ハンバーガーを取得する」というタスクは終了しました⏹。
それからカウンターへ行き 🔀、いま完了した初期のタスク ⏯ に戻って、ハンバーガーを受け取り、礼を言ってテーブルに持っていきます。これでカウンターとのやり取りというステップ/タスクは完了 ⏹ です。その結果として「ハンバーガーを食べる」🔀 ⏯ という新しいタスクが生まれますが、先の「ハンバーガーを受け取る」タスクは完了 ⏹ しています
### 並列ハンバーガー
### 並列ハンバーガー { #parallel-burgers }
これらが「並行ハンバーガー」ではなく、「並列ハンバーガー」であるとしましょう。
今度は、これが「並行ハンバーガー」ではなく「並列ハンバーガー」だと想像しましょう。
あなたは好きな人😍と並列ファストフード🍔を買おうとしています。
あなたは好きな人と並列ファストフードを買いに行きます。
列に並んでいますが、何人かの料理人兼、レジ係 (8人としましょう) 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳があなたの前にいる人達の注文を受けつけています。
複数のレジ係 (例えば 8 人) が同時に料理人でもあり、前の人たちの注文を受けています。
8人のレジ係がそれぞれ自分で注文を受けるや否や、次の注文を受ける前にハンバーガーを準備するので、あなたの前の人達はカウンターを離れずに、ハンバーガー🍔ができるのを待っています🕙
8 人のレジ係はそれぞれ、次の注文を取る前にすぐに調理に取りかかるため、あなたの前の人たちはカウンターを離れず、ハンバーガーができるのを待っています
それからいよいよあなたの番になり、好きな人😍と自分のために、2つの非常に豪華なハンバーガー🍔を注文します。
<img src="/img/async/parallel-burgers/parallel-burgers-01.png" class="illustration">
料金を支払います💸
ようやくあなたの番になり、好きな人と自分のために豪華なハンバーガーを 2 つ注文します
レジ係はキッチンに行きます👨‍🍳
支払いをします 💸
あなたはカウンターの前に立って待ちます🕙。番号札がないので誰もあなたよりも先にハンバーガー🍔を取らないようにします。
<img src="/img/async/parallel-burgers/parallel-burgers-02.png" class="illustration">
あなたと好きな人😍は忙しいので、誰もあなたの前に来させませんし、あなたのハンバーガーが到着したとき🕙に誰にも取ることを許しません。あなたは好きな人に注意を払えません😞
レジ係はキッチンに向かいます
これは「同期」作業であり、レジ係/料理人👨‍🍳と「同期」します。レジ係/料理人👨‍🍳がハンバーガー🍔を完成させてあなたに渡すまで待つ🕙必要があり、ちょうどその完成の瞬間にそこにいる必要があります。そうでなければ、他の誰かに取られるかもしれません
番号札がないため、他の誰かに先に取られないよう、カウンターの前で立って待ちます 🕙
その後、カウンターの前で長い時間待ってから🕙、ついにレジ係/料理人👨‍🍳がハンバーガー🍔を渡しに戻ってきます。
<img src="/img/async/parallel-burgers/parallel-burgers-03.png" class="illustration">
ハンバーガー🍔を取り、好きな人😍とテーブルに行きます。
あなたと好きな人は、誰にも割り込まれずハンバーガーが来たらすぐ受け取れるよう見張っているので、好きな人に注意を向けられません。😞
ただ食べるだけ、それでおしまいです。🍔⏹
これは「同期」的な作業です。レジ係/料理人 👨‍🍳 と「同期」しています。レジ係/料理人 👨‍🍳 がハンバーガーを作り終えて手渡すその瞬間に、待って 🕙 その場にいなければなりません。そうでないと他の誰かに取られるかもしれません
ほとんどの時間、カウンターの前で待つのに費やされていたので🕙、あまり話したりいちゃつくことはありませんでした😞。
<img src="/img/async/parallel-burgers/parallel-burgers-04.png" class="illustration">
長い時間 🕙 カウンター前で待った後、ようやくレジ係/料理人 👨‍🍳 がハンバーガーを持って戻ってきます。
<img src="/img/async/parallel-burgers/parallel-burgers-05.png" class="illustration">
ハンバーガーを受け取り、好きな人とテーブルに行きます。
食べて、おしまいです。⏹
<img src="/img/async/parallel-burgers/parallel-burgers-06.png" class="illustration">
ほとんどの時間をカウンター前で待つ 🕙 のに費やしたため、あまり話したり、いちゃついたりできませんでした。😞
/// info | 情報
美しいイラストは <a href="https://www.instagram.com/ketrinadrawsalot" class="external-link" target="_blank">Ketrina Thompson</a> によるものです。🎨
///
---
この並列ハンバーガーのシナリオでは、あなたは2つのプロセッサを備えたコンピュータ/プログラム🤖 (あなたとあなたの好きな人😍) であり、両方とも待機🕙していて、彼らは「カウンターで待機🕙」することに専念しています⏯。
この「並列ハンバーガー」のシナリオでは、あなたは 2 つのプロセッサ (あなたと好きな人) を持つコンピュータ/プログラム 🤖 で、どちらも長い間 🕙「カウンターでの待機」に注意 ⏯ を専念しています
ファストフード店には8つのプロセッサ (レジ係/料理人) 👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳👨🍳があります。一方、並行ハンバーガー店には2人 (レジ係と料理人) 💁👨‍🍳しかいなかったかもしれません。
ファストフード店には 8 個のプロセッサ (レジ係/料理人) があります。一方、並行ハンバーガーの店には (レジ係 1、人、料理人 1 人の) 2 個しかなかったかもしれません。
しかし、それでも、最終的な体験は最高ではありません😞。
それでも、最終的な体験は最良とは言えません。😞
---
これは、ハンバーガー🍔の話と同等な話になります。
これはハンバーガーにおける並列版の物語です。🍔
より「現実的な」例として、銀行を想像してみてください。
最近まで、ほとんどの銀行は複数の窓口👨‍💼👨‍💼👨‍💼👨‍💼に、行列🕙🕙🕙🕙🕙🕙🕙🕙ができていました。
つい最近まで、ほとんどの銀行には複数の窓口係 👨‍💼👨‍💼👨‍💼👨‍💼 と長い行列 🕙🕙🕙🕙🕙🕙🕙🕙 がありました。
すべての窓口で、次々と、一人の客とすべての作業を行います👨‍💼⏯.
各窓口係が、一人ずつ、すべての作業を順番に行います 👨‍💼⏯。
の上、長時間、列に並ばなければいけません🕙。そうしないと、順番が回ってきません
して、長時間 🕙 行列で待たなければ順番を失います
銀行🏦での用事にあなたの好きな人😍を連れて行きたくはないでしょう。
銀行の用事 🏦 に、好きな人 😍 を連れて行きたいとは思わないでしょう。
### ハンバーガーのまとめ
### ハンバーガーのまとめ { #burger-conclusion }
この「好きな人とのファストフードハンバーガー」のシナリオでは、待機🕙が多いため、並行システム⏸🔀⏯を使用する方がはるかに理にかなっています。
この「好きな人とファストフード」のシナリオでは、待ち時間 🕙 が多いため、並行システム ⏸🔀⏯ を使う方がはるかに理にかなっています。
これは、ほとんどのWebアプリケーションに当てはまります。
これは、ほとんどの Web アプリケーションに当てはまります。
多くのユーザーがいますが、サーバーは、あまり強くない回線でのリクエストの送信を待機🕙しています。
とても多くのユーザーがいますが、サーバは彼らのあまり速くない回線からリクエストが届くのを待ち 🕙、
して、レスポンスが返ってくるのをもう一度待機🕙します
の後、レスポンスが戻ってくるのをまた待ちます 🕙
この「待機🕙」はマイクロ秒単位ですが、それでも、すべて合算すると、最終的にはかなり待機することになります。
この「待ち」🕙 はマイクロ秒単位で測られますが、すべてを合計すると、結局かなりの待ちになります。
これが、Web APIへの非同期⏸🔀⏯コードの利用が理にかなっている理由です。
だからこそ、Web API には非同期 ⏸🔀⏯ コードを使うのが理にかなっています。
ほとんどの既存の人気のあるPythonフレームワーク (FlaskやDjangoを含む) は、Pythonの新しい非同期機能ができる前に作成されました。したがって、それらをデプロイする方法は、並列実行と、新機能ほど強力ではない古い形式の非同期実行をサポートします。
これが、NodeJS を人気にした要因 (NodeJS 自体は並列ではありません) であり、プログラミング言語としての Go の強みでもあります。
しかし、WebSocketのサポートを追加するために、非同期Web Python (ASGI) の主な仕様はDjangoで開発されました
そして、それが **FastAPI** で得られるパフォーマンスの水準です
そのような非同期性がNodeJSを人気にした理由です (NodeJSは並列ではありませんが)。そして、プログラミング言語としてのGoの強みでもあります
さらに、並列性と非同期性を同時に活用できるため、テストされた多くの NodeJS フレームワークより高い性能を発揮し、C に近いコンパイル言語である Go と同等の性能になります <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(すべて Starlette のおかげです)</a>
そして、それは**FastAPI**で得られるパフォーマンスと同じレベルです。
### 並行処理は並列処理より優れている? { #is-concurrency-better-than-parallelism }
また、並列処理と非同期処理を同時に実行できるため、テスト済みのほとんどのNodeJSフレームワークよりも高く、Goと同等のパフォーマンスが得られます。Goは、Cに近いコンパイル言語です <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(Starletteに感謝します)</a>
いいえ!それがこの話の教訓ではありません
### 並行は並列よりも優れていますか?
並行処理は並列処理とは異なります。そして多くの待ち時間を伴う**特定の**シナリオでは優れています。そのため、一般に Web アプリ開発では並列処理よりはるかに適しています。しかし、すべてに対して最良というわけではありません。
いや!それはこの話の教訓ではありません
バランスを取るために、次の短い物語を想像してください
並行処理は並列処理とは異なります。多くの待機を伴う**特定の**シナリオに適しています。そのため、一般に、Webアプリケーション開発では並列処理よりもはるかに優れています。しかし、すべてに対してより良いというわけではありません
> 大きくて汚れた家を掃除しなければならない
なので、バランスをとるために、次の物語を想像して下さい:
> あなたは大きくて汚れた家を掃除する必要があります。
*はい、以上です*。
*はい、これで物語は全部です*。
---
待機🕙せず、家の中の複数の場所でたくさんの仕事をするだけです。
どこにも待ち 🕙 はなく、家の複数箇所で大量の作業があるだけです。
あなたはハンバーガーの例のように、最初はリビングルーム、次にキッチンのように順番にやっていくことができますが、何かを待機🕙しているわけではなく、ただひたすらに掃除をするだけで、順番は何にも影響しません。
ハンバーガーの例のように順番を決めて、まずリビング、次にキッチン、と進めてもよいのですが、何かを待つ 🕙 わけではなく、ひたすら掃除するだけなので、順番は何も影響しません。
順番の有無に関係なく (並行に) 同じ時間がかかり、同じ量の作業が行われることになるでしょう
順番の有無 (並行性の有無) に関係なく、終了までに同じ時間がかかり、同じ作業量をこなすことになります
しかし、この場合、8人の元レジ係/料理人/現役清掃員👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳を手配できて、それぞれ (さらにあなたも) が家の別々の場所を掃除できれば、追加の助けを借りて、すべての作業を**並列**に行い、はるかに早く終了できるでしょう
しかしこの場合、8 人の元レジ係/料理人/現清掃員を連れてきて、それぞれ (あなたも加えて) 家の別々のエリアを掃除できれば、**並列** に作業でき、より早く終えられます
このシナリオでは、清掃員 (あなたを含む) のそれぞれがプロセッサとなり、それぞれの役割を果たします。
このシナリオでは、各清掃員 (あなたを含む) がプロセッサであり、それぞれが自分の役割を果たします。
また、実行時間のほとんどは (待機ではなく) 実際の作業に費やされ、コンピュータでの作業は<abbr title="Central Processing Unit">CPU</abbr>によって行われます。これらの問題は「CPUバウンド」と言います。
そして実行時間の大半は (待ちではなく) 実作業が占め、コンピュータでの作業は <abbr title="Central Processing Unit - 中央処理装置">CPU</abbr> によって行われます。これらの問題は「CPU バウンド」と呼ばれます。
---
CPUバウンド操作の一般的な例は、複雑な数学処理が必要なものです。
CPU バウンドな操作の一般的な例は、複雑な数値処理が必要なものです。
例えば:
* **オーディオ****画像処理**
* **コンピュータビジョン**: 画像は数百万のピクセルで構成され、各ピクセルには3つの値/色があり、通常、これらのピクセルで何かを同時に計算する必要がある処理
* **機械学習**: 通常、多くの「行列」と「ベクトル」の乗算が必要です。巨大なスプレッドシートに数字を入れて、それを同時に全部掛け合わせることを考えてみてください。
* **ディープラーニング**: これは機械学習のサブフィールドであるため、同じことが当てはまります。乗算する数字がある単一のスプレッドシートではなく、それらの膨大な集合で、多くの場合、それらのモデルを構築および/または使用するために特別なプロセッサを使用します。
* **コンピュータビジョン**: 画像は数百万のピクセルで構成され、各ピクセルには 3 つの値/色があり、通常、それらのピクセル上で同時に何かを計算する必要があります
* **機械学習**: 多くの「行列」や「ベクトル」の乗算が必要になります。巨大なスプレッドシートに数字が入っていて、それらを同時にすべて掛け合わせることを想像してください。
* **ディープラーニング**: 機械学習のサブフィールドなので同様です。掛け合わせる数字が 1 つのスプレッドシートではなく膨大な集合であり、多くの場合、それらのモデルを構築/利用するための特別なプロセッサを使います。
### 並行処理 + 並列処理: Web + 機械学習
### 並行処理 + 並列処理: Web + 機械学習 { #concurrency-parallelism-web-machine-learning }
**FastAPI**を使用すると、Web開発で非常に一般的な並行処理 (NodeJSの主な魅力と同じもの) を利用できます。
**FastAPI** では、Web 開発で非常に一般的な並行処理 (NodeJS の主な魅力と同じ) を活用できます。
ただし、機械学習システムのような **CPUバウンド** ワークロードに対して、並列処理とマルチプロセッシング (複数のプロセスが並列で実行される) の利点を活用することもできます。
同時に、機械学習システムのような **CPU バウンド** なワークロードに対して、並列処理やマルチプロセッシング (複数プロセスの並列実行) の利点も活用できます。
さらに、Pythonが**データサイエンス**、機械学習、特にディープラーニングの主要言語であるという単純な事実により、FastAPIはデータサイエンス/機械学習のWeb APIおよびアプリケーション (他の多くのアプリケーションとの) に非常によく適合しています。
さらに、Python **データサイエンス**、機械学習、特にディープラーニングの主要言語であるという事実も相まって、FastAPI はデータサイエンス/機械学習の Web API やアプリケーション (ほか多数) に非常に適しています。
本番環境でこの並列処理を実現する方法については、[デプロイ](deployment/index.md){.internal-link target=_blank}に関するセクションを参照してください。
本番環境でこの並列性を実現する方法は、[デプロイ](deployment/index.md){.internal-link target=_blank} のセクションを参照してください。
## `async``await`
## `async``await` { #async-and-await }
現代的なバージョンのPythonには、非同期コードを定義する非常に直感的な方法があります。これにより、通常の「シーケンシャル」コードのように見え、適切なタイミングで「待機」します。
モダンな Python には、非同期コードをとても直感的に定義する方法があります。これにより、通常の「シーケンシャル」なコードのように書けて、適切なタイミングで「待ち」を行ってくれます。
結果を返す前に待機する必要があり、これらの新しいPython機能をサポートする操作がある場合は、次のようにコーディングできます。
結果を返す前に待ちが必要で、これらの新しい Python 機能をサポートしている操作がある場合、次のように書けます。
```Python
burgers = await get_burgers(2)
```
カギは `await` です。結果を `burgers`に保存する前に、`get_burgers(2)`の処理🕙の完了を待つ⏸必要があることをPythonに伝えます。これでPythonは、その間に (別のリクエストを受信するなど) 何か他のことができる🔀⏯ことを知ります。
ここでの鍵は `await` です。`burgers` に結果を保存する前に、`get_burgers(2)` がやるべきことを終えるのを ⏸ 待つ 🕙 ように Python に伝えます。これにより Python は、その間に (別のリクエストを受け取るなど) ほかのことを 🔀 ⏯ できると分かります。
`await` が機能するためには、非同期処理をサポートする関数内にある必要があります。これは、`async def` で関数を宣言するだけでよいです:
`await` が機能するには、この非同期性をサポートする関数の内部でなければなりません。そのためには `async def` で宣言します:
```Python hl_lines="1"
async def get_burgers(number: int):
# ハンバーガーを作成するために非同期処理を
# ハンバーガーを作るために非同期処理を行
return burgers
```
...`def` のわりに:
...`def` のわりに:
```Python hl_lines="2"
# 非同期ではない
# これは非同期ではない
def get_sequential_burgers(number: int):
# ハンバーガーを作成するためにシーケンシャルな処理を
# ハンバーガーを作るためにシーケンシャルな処理を行
return burgers
```
`async def` を使用すると、Pythonにその関数内で `await` 式 (その関数の実行を「一時停止⏸」し、結果が戻るまで他の何かを実行🔀する) を認識しなければならないと伝えることができます。
`async def` 関数を呼び出すときは、「await」しなければなりません。したがって、これは機能しません:
`async def` を使うと、Python はその関数内で `await` 式に注意し、関数の実行を「一時停止」⏸ してほかのことをしに行き 🔀、戻ってくることができると分かります。
`async def` な関数を呼ぶときは「await」しなければなりません。したがって、次は動きません:
```Python
# get_burgersはasync defで定義されているので動作しない
# 動きません。get_burgers は async def で定義されています
burgers = get_burgers(2)
```
---
したがって、 `await` で呼び出すことができるライブラリを使用している場合は、次のように `async def` を使用して、それを使用する*path operation 関数*を作成する必要があります:
そのため、`await` で呼べると謳っているライブラリを使っている場合は、それを使う *path operation 関数*`async def` で作る必要があります。例えば:
```Python hl_lines="2-3"
@app.get('/burgers')
@ -314,86 +349,96 @@ async def read_burgers():
return burgers
```
### より発展的な技術詳細
### より発展的な技術詳細 { #more-technical-details }
`await``async def` で定義された関数内でのみ使用できることがわかったかと思います
`await``async def` で定義された関数の内部でしか使えないことに気づいたかもしれません
しかし同時に、`async def` で定義された関数は「awaitされる」必要があります。なので、`async def` を持つ関数は、`async def` で定義された関数内でのみ呼び出せます
同時に、`async def` で定義された関数は「await」される必要があります。つまり、`async def` を持つ関数は、やはり `async def` で定義された関数の内部からしか呼べません
では、このニワトリと卵の問題について、最初の `async` 関数をどのように呼び出すのでしょうか?
では、ニワトリと卵の話のように、最初の `async` 関数はどう呼ぶのでしょうか?
**FastAPI**を使用している場合、その「最初の」関数が*path operation 関数*であり、FastAPIが正しく実行する方法を知っているので、心配する必要はありません
**FastAPI** を使っている場合は心配ありません。その「最初の」関数は *path operation 関数* で、FastAPI が適切に実行してくれます
しかし、FastAPI以外で `async` / `await` を使用したい場合は、<a href="https://docs.python.org/3/library/asyncio-task.html#coroutine" class="external-link" target="_blank">公式Pythonドキュメントを参照して下さい</a>
しかし、FastAPI を使わずに `async` / `await` を使いたい場合もあります
### 非同期コードの他の形式
### 自分で async コードを書く { #write-your-own-async-code }
`async``await` を使用するスタイルは、この言語では比較的新しいものです。
Starlette (**FastAPI** も) は <a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> の上に構築されており、標準ライブラリの <a href="https://docs.python.org/3/library/asyncio-task.html" class="external-link" target="_blank">asyncio</a><a href="https://trio.readthedocs.io/en/stable/" class="external-link" target="_blank">Trio</a> の両方に対応しています。
非同期コードの操作がはるかに簡単になります。
特に、あなた自身のコード内で、より高度なパターンを必要とする発展的な並行処理のユースケースに対して、<a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> を直接使えます。
等価な (またはほとんど同一の) 構文が、最近のバージョンのJavaScript (ブラウザおよびNodeJS) にも最近組み込まれました
仮に FastAPI を使っていなくても、<a href="https://anyio.readthedocs.io/en/stable/" class="external-link" target="_blank">AnyIO</a> で独自の async アプリケーションを書けば、高い互換性と利点 (例: 構造化並行性) を得られます
しかし、その前は、非同期コードの処理はかなり複雑で難解でした
私は AnyIO の上に薄い層として、型注釈を少し改善し、より良い**補完**や**インラインエラー**などを得るための別ライブラリも作りました。また、**理解**して**自分で async コードを書く**のに役立つフレンドリーなイントロ/チュートリアルもあります: <a href="https://asyncer.tiangolo.com/" class="external-link" target="_blank">Asyncer</a>。特に、**async コードと通常の** (ブロッキング/同期) **コードを組み合わせる**必要がある場合に有用です
以前のバージョンのPythonでは、スレッドや<a href="https://www.gevent.org/" class="external-link" target="_blank">Gevent</a>が利用できました。しかし、コードは理解、デバック、そして、考察がはるかに複雑です。
### 非同期コードの他の形式 { #other-forms-of-asynchronous-code }
以前のバージョンのNodeJS / ブラウザJavaScriptでは、「コールバック」を使用していました。これは、「コールバック地獄」につながります。
`async``await` を使うこのスタイルは、言語としては比較的新しいものです。
## コルーチン
しかし、これにより非同期コードの取り扱いは大幅に簡単になります。
**コルーチン**は、`async def` 関数によって返されるものを指す非常に洒落た用語です。これは、開始できて、いつか終了する関数のようなものであるが、内部に `await` があるときは内部的に一時停止⏸されることもあるものだとPythonは認識しています
同等 (ほぼ同一) の構文が最近の JavaScript (ブラウザと NodeJS) にも導入されました
`async``await` を用いた非同期コードを使用するすべての機能は、「コルーチン」を使用するものとして何度もまとめられています。Goの主要機能である「ゴルーチン」に相当します
それ以前は、非同期コードの扱いはかなり複雑で難解でした
## まとめ
以前の Python ではスレッドや <a href="https://www.gevent.org/" class="external-link" target="_blank">Gevent</a> を使えましたが、コードの理解・デバッグ・思考がはるかに難しくなります。
上述したフレーズを見てみましょう:
以前の NodeJS / ブラウザ JavaScript では「コールバック」を使っており、「コールバック地獄」を招きました。
> 現代版のPythonは「**非同期コード**」を、「**コルーチン**」と称されるものを利用してサポートしています。これは **`async``await`** 構文を用います。
## コルーチン { #coroutines }
今では、この意味がより理解できるはずです。✨
**コルーチン**は、`async def` 関数が返すものを指す、ちょっと洒落た用語です。Python はそれを、開始できていつか終了する関数のようなものとして扱いますが、内部に `await` があるたびに内部的に一時停止 ⏸ するかもしれないものとして認識します。
(Starletteを介して) FastAPIに力を与えて、印象的なパフォーマンスを実現しているものはこれがすべてです。
`async``await` を用いた非同期コードの機能全体は、しばしば「コルーチンを使う」と要約されます。これは Go の主要機能「Goroutines」に相当します。
## 非常に発展的な技術的詳細
## まとめ { #conclusion }
上のフレーズをもう一度見てみましょう:
> モダンな Python は **「非同期コード」** を **「コルーチン」** と呼ばれる仕組みでサポートしており、構文は **`async``await`** です。
今なら、より意味が分かるはずです。✨
これらすべてが (Starlette を通じて) FastAPI を支え、印象的なパフォーマンスを実現しています。
## 非常に発展的な技術的詳細 { #very-technical-details }
/// warning | 注意
恐らくスキップしても良いでしょう。
おそらく読み飛ばしても大丈夫です
この部分は**FastAPI**の仕組みに関する非常に技術的な詳細です。
れは **FastAPI** の内部動作に関する、とても技術的な詳細です。
かなりの技術知識 (コルーチン、スレッド、ブロッキングなど) があり、FastAPIが `async def` と通常の `def` をどのように処理するか知りたい場合は、先に進んでください。
(コルーチン、スレッド、ブロッキング等の) 技術知識があり、FastAPI が `async def` と通常の `def` をどう扱うかに興味がある場合は、読み進めてください。
///
### Path operation 関数
### Path operation 関数 { #path-operation-functions }
*path operation 関数*`async def` の代わりに通常の `def` で宣言すると、(サーバーをブロックするので) 直接呼び出す代わりに外部スレッドプール (awaitされる) で実行されます。
*path operation 関数*`async def` ではなく通常の `def` で宣言した場合、(サーバをブロックしてしまうため) 直接呼び出されるのではなく、外部のスレッドプールで実行され、それを待機します。
上記の方法と違った方法の別の非同期フレームワークから来ており、小さなパフォーマンス向上 (約100ナ秒) のために通常の `def` を使用して些細な演算のみ行う *path operation 関数* を定義するのに慣れている場合は、**FastAPI**ではまったく逆の効果になることに注意してください。このような場合、*path operation 関数* がブロッキング<abbr title="力/出力: ディスクの読み取りまたは書き込み、ネットワーク通信。">I/O</abbr>を実行しないのであれば、`async def` の使用をお勧めします。
上記とは異なる動作の別の非同期フレームワークから来ており、ほんのわずかなパフォーマンス向上 (約 100 ナノ秒) を狙って、計算のみの些細な *path operation 関数* を素の `def` で定義することに慣れている場合、**FastAPI** では効果がまったく逆になる点に注意してください。これらの場合、*path operation 関数* がブロッキング<abbr title="Input/Output - 入出力: ディスクの読み取りまたは書き込み、ネットワーク通信。">I/O</abbr> を行うコードを使っていない限り、`async def` を使った方が良いです。
それでも、どちらの状況でも、**FastAPI**が過去のフレームワークよりも (またはそれに匹敵するほど) [高速になる](index.md#_10){.internal-link target=_blank}可能性があります。
それでも、どちらの状況でも、**FastAPI** はあなたが以前使っていたフレームワークよりも (少なくとも同等に) [高速である](index.md#performance){.internal-link target=_blank} 可能性が高いです。
### 依存関係
### 依存関係 { #dependencies }
依存関係についても同様です。依存関係が `async def` ではなく標準の `def` 関数である場合、外部スレッドプールで実行されます。
[依存関係](tutorial/dependencies/index.md){.internal-link target=_blank} についても同様です。依存関係が `async def` ではなく標準の `def` 関数である場合、外部スレッドプールで実行されます。
### サブ依存関係
### サブ依存関係 { #sub-dependencies }
(関数定義のパラメーターとして) 相互に必要な複数の依存関係とサブ依存関係を設定できます。一部は `async def` で作成され、他の一部は通常の `def` で作成されます。それでも動作し、通常の `def`で作成されたものは、「awaitされる」代わりに (スレッドプールから) 外部スレッドで呼び出されます。
複数の依存関係や [サブ依存関係](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} を (関数定義のパラメータとして) 相互に要求させられます。その一部は `async def`、他は通常の `def` で作られていても動作します。通常の `def` で作られたものは「await」される代わりに、外部スレッドプールからスレッド上で呼び出されます。
### その他のユーティリティ関数
### その他のユーティリティ関数 { #other-utility-functions }
あなたが直接呼び出すユーティリティ関数は通常の `def` または `async def` で作成でき、FastAPIは呼び出す方法に影響を与えません。
あなたが直接呼び出すユーティリティ関数は、通常の `def` でも `async def` でも構いません。FastAPI はその呼び出し方に影響を与えません。
これは、FastAPIが呼び出す関数と対照的です: *path operation 関数*と依存関係
これは、FastAPI があなたの代わりに呼び出す関数 (すなわち *path operation 関数* と依存関係) とは対照的です
ユーティリティ関数が `def` を使用した通常の関数である場合、スレッドプールではなく直接 (コードで記述したとおりに) 呼び出されます。関数が `async def` を使用して作成されている場合は、呼び出す際に `await` する必要があります。
ユーティリティ関数が `def` の通常関数であれば、(あなたのコードに書いたとおりに) 直接呼び出され、スレッドプールでは実行されません。関数が `async def` で作られている場合は、その関数を呼ぶときに `await` すべきです。
---
繰り返しになりますが、これらは非常に技術的な詳細であり、検索して辿り着いた場合は役立つでしょう。
繰り返しになりますが、これらは非常に技術的な詳細で、該当事項を検索してここにたどり着いた場合には役立つでしょう。
それ以外の場合は、上記のセクションのガイドラインで問題ないはずです: <a href="#_1">急いでいますか?</a>
それ以外の場合は、上のセクションのガイドラインに従えば十分です: <a href="#in-a-hurry">急いでいますか?</a>

View File

@ -0,0 +1,24 @@
# クラウドプロバイダへの FastAPI デプロイ { #deploy-fastapi-on-cloud-providers }
FastAPI アプリケーションは、実質的にどのようなクラウドプロバイダでもデプロイできます。
多くの場合、主要なクラウドプロバイダは FastAPI をデプロイするためのガイドを提供しています。
## FastAPI Cloud { #fastapi-cloud }
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** は、**FastAPI** の作者と同じチームによって作られています。
API の**構築**、**デプロイ**、**アクセス**までのプロセスを、最小限の手間で効率化します。
FastAPI でアプリを開発するときと同じ**開発者体験**を、クラウドへの**デプロイ**にももたらします。🎉
FastAPI Cloud は、*FastAPI and friends* オープンソースプロジェクトの主要なスポンサーかつ資金提供元です。✨
## クラウドプロバイダ - スポンサー { #cloud-providers-sponsors }
他にもいくつかのクラウドプロバイダが ✨ [**FastAPI をスポンサーしています**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨。🙇
それらのガイドを参考にし、サービスを試してみるのもよいでしょう:
* <a href="https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi" class="external-link" target="_blank">Render</a>
* <a href="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi" class="external-link" target="_blank">Railway</a>

View File

@ -29,7 +29,6 @@
## セキュリティ - HTTPS { #security-https }
<!-- NOTE: https.md written in Japanese does not exist, so it redirects to English one -->
[前チャプターのHTTPSについて](https.md){.internal-link target=_blank}では、HTTPSがどのようにAPIを暗号化するのかについて学びました。
通常、アプリケーションサーバにとって**外部の**コンポーネントである**TLS Termination Proxy**によって提供されることが一般的です。このプロキシは通信の暗号化を担当します。
@ -193,7 +192,6 @@ FastAPI アプリケーションでは、Uvicorn を実行する `fastapi` コ
同じAPIプログラムの**複数のプロセス**を実行する場合、それらは一般的に**Workerワーカー**と呼ばれます。
### ワーカー・プロセス と ポート { #worker-processes-and-ports }
<!-- NOTE: https.md written in Japanese does not exist, so it redirects to English one -->
[HTTPSについて](https.md){.internal-link target=_blank}のドキュメントで、1つのサーバーで1つのポートとIPアドレスの組み合わせでリッスンできるのは1つのプロセスだけであることを覚えていますでしょうか

View File

@ -14,7 +14,7 @@ Linuxコンテナの使用には、**セキュリティ**、**反復可能性(
<summary>Dockerfile Preview 👀</summary>
```Dockerfile
FROM python:3.9
FROM python:3.14
WORKDIR /code
@ -166,7 +166,7 @@ def read_item(item_id: int, q: str | None = None):
```{ .dockerfile .annotate }
# (1)!
FROM python:3.9
FROM python:3.14
# (2)!
WORKDIR /code
@ -392,7 +392,7 @@ FastAPI が単一のファイル、例えば `./app` ディレクトリのない
そうすれば、`Dockerfile`の中にファイルをコピーするために、対応するパスを変更するだけでよいです:
```{ .dockerfile .annotate hl_lines="10 13" }
FROM python:3.9
FROM python:3.14
WORKDIR /code
@ -456,7 +456,7 @@ TraefikはDockerやKubernetesなどと統合されているので、コンテナ
## レプリケーション - プロセス数 { #replication-number-of-processes }
**Kubernetes** や Docker Swarm モード、Nomad、あるいは複数のマシン上で分散コンテナを管理するための同様の複雑なシステムを使ってマシンの<abbr title="A group of machines that are configured to be connected and work together in some way. - ある方法で接続され、連携して動作するように構成されたマシンの集まり">cluster</abbr>を構成している場合、 各コンテナでWorkerを持つUvicornのような**プロセスマネージャ**を使用する代わりに、**クラスター・レベル**で**レプリケーション**を処理したいと思うでしょう。
**Kubernetes** や Docker Swarm モード、Nomad、あるいは複数のマシン上で分散コンテナを管理するための同様の複雑なシステムを使ってマシンの<dfn title="ある方法で接続され、連携して動作するように構成されたマシンの集まり">クラスタ</dfn>を構成している場合、 各コンテナでWorkerを持つUvicornのような**プロセスマネージャ**を使用する代わりに、**クラスター・レベル**で**レプリケーション**を処理したいと思うでしょう。
Kubernetesのような分散コンテナ管理システムの1つは通常、入ってくるリクエストの**ロードバランシング**をサポートしながら、**コンテナのレプリケーション**を処理する統合された方法を持っています。このことはすべて**クラスタレベル**にてです。
@ -501,7 +501,7 @@ HTTPSに使われるものと同じ**TLS Termination Proxy**コンポーネン
そのような場合、`--workers` コマンドラインオプションを使って、実行したいワーカー数を設定できます:
```{ .dockerfile .annotate }
FROM python:3.9
FROM python:3.14
WORKDIR /code

View File

@ -0,0 +1,65 @@
# FastAPI Cloud { #fastapi-cloud }
<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>**コマンド1つ** でデプロイできます。まだならウェイティングリストにご登録ください。🚀
## ログイン { #login }
すでに **FastAPI Cloud** アカウントをお持ちであることを確認してください(ウェイティングリストからご招待しています 😉)。
次にログインします:
<div class="termy">
```console
$ fastapi login
You are logged in to FastAPI Cloud 🚀
```
</div>
## デプロイ { #deploy }
では、**コマンド1つ** でアプリをデプロイします:
<div class="termy">
```console
$ fastapi deploy
Deploying to FastAPI Cloud...
✅ Deployment successful!
🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev
```
</div>
以上です!その URL からアプリにアクセスできます。✨
## FastAPI Cloud について { #about-fastapi-cloud }
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>** は、**FastAPI** の作者とチームによって開発されています。
最小限の手間で API を**構築**・**デプロイ**・**利用**できるように工程を簡素化します。
FastAPI での開発と同じ**開発者体験**を、クラウドへの**デプロイ**にももたらします。🎉
さらに、アプリのデプロイ時に必要となる多くの事項も任せられます。例えば:
* HTTPS
* レプリケーション(リクエストに基づくオートスケーリング付き)
* など
FastAPI Cloud は、*FastAPI and friends* のオープンソースプロジェクトに対する主要スポンサーかつ資金提供元です。✨
## 他のクラウドプロバイダーへのデプロイ { #deploy-to-other-cloud-providers }
FastAPI はオープンソースで標準に基づいています。お好みの任意のクラウドプロバイダーに FastAPI アプリをデプロイできます。
各クラウドプロバイダーのガイドに従って FastAPI アプリをデプロイしてください。🤓
## 自分のサーバーへのデプロイ { #deploy-your-own-server }
この**デプロイ**ガイドの後半では詳細も解説します。何が起きているのか、何が必要なのか、そして自分のサーバーを含めて FastAPI アプリを自力でデプロイする方法が分かるようになります。🤓

View File

@ -28,7 +28,7 @@ HTTPSは単に「有効」か「無効」かで決まるものだと思いがち
* **デフォルトでは**、**IPアドレスごとに1つのHTTPS証明書**しか持てないことになります。
* これは、サーバーの規模やアプリケーションの規模に寄りません。
* しかし、これには**解決策**があります。
* **TLS**プロトコル(HTTPの前に、TCPレベルで暗号化を処理するもの)には、**<a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication">SNI</abbr></a>**と呼ばれる**拡張**があります。
* **TLS**プロトコル(HTTPの前に、TCPレベルで暗号化を処理するもの)には、**<a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication - サーバー名表示">SNI</abbr></a>**と呼ばれる**拡張**があります。
* このSNI拡張機能により、1つのサーバー**単一のIPアドレス**を持つ)が**複数のHTTPS証明書**を持ち、**複数のHTTPSドメイン/アプリケーション**にサービスを提供できるようになります。
* これが機能するためには、**パブリックIPアドレス**でリッスンしている、サーバー上で動作している**単一の**コンポーネント(プログラム)が、サーバー内の**すべてのHTTPS証明書**を持っている必要があります。
* セキュアな接続を取得した**後**でも、通信プロトコルは**HTTPのまま**です。
@ -66,7 +66,7 @@ Let's Encrypt以前は、これらの**HTTPS証明書**は信頼できる第三
ステップの初めは、**ドメイン名**を**取得すること**から始まるでしょう。その後、DNSサーバーおそらく同じクラウドプロバイダーに設定します。
おそらくクラウドサーバー(仮想マシン)かそれに類するものを手に入れ、<abbr title="That doesn't change 変わらない">fixed</abbr> **パブリックIPアドレス**を持つことになるでしょう。
おそらくクラウドサーバー(仮想マシン)かそれに類するものを手に入れ、<dfn title="時間とともに変化しない。動的ではない。">固定の</dfn> **パブリックIPアドレス**を持つことになるでしょう。
DNSサーバーでは、**取得したドメイン**をあなたのサーバーのパプリック**IPアドレス**に向けるレコード(「`A record`」)を設定します。

View File

@ -1,12 +1,82 @@
# 手動デプロイ
# サーバーを手動で実行する { #run-a-server-manually }
**FastAPI** を手動でデプロイすることもできます。
## fastapi run コマンドを使う { #use-the-fastapi-run-command }
以下の様なASGI対応のサーバをインストールする必要があります:
結論として、FastAPI アプリケーションを提供するには `fastapi run` を使います:
//// tab | Uvicorn
<div class="termy">
* <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a>, uvloopとhttptoolsを基にした高速なASGIサーバ。
```console
$ <font color="#4E9A06">fastapi</font> run <u style="text-decoration-style:solid">main.py</u>
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting production server 🚀
Searching for package file structure from directories
with <font color="#3465A4">__init__.py</font> files
Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
<span style="background-color:#007166"><font color="#D3D7CF"> module </font></span> 🐍 main.py
<span style="background-color:#007166"><font color="#D3D7CF"> code </font></span> Importing the FastAPI app object from the module with
the following code:
<u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
<span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://0.0.0.0:8000</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://0.0.0.0:8000/docs</u></font>
Logs:
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>2306215</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://0.0.0.0:8000</u></font> <b>(</b>Press CTRL+C
to quit<b>)</b>
```
</div>
これでほとんどのケースは動作します。😎
このコマンドは、たとえばコンテナやサーバー内で **FastAPI** アプリを起動するのに使えます。
## ASGIサーバー { #asgi-servers }
少し詳しく見ていきます。
FastAPI は、Python の Web フレームワークとサーバーのための標準である <abbr title="Asynchronous Server Gateway Interface - 非同期サーバーゲートウェイインターフェース">ASGI</abbr> を使います。FastAPI は ASGI Web フレームワークです。
リモートのサーバーマシンで **FastAPI** アプリケーション(や他の ASGI アプリケーション)を実行するのに主に必要なのは **Uvicorn** のような ASGI サーバープログラムです。これは `fastapi` コマンドにデフォルトで含まれています。
他にもいくつかの選択肢があります:
* <a href="https://www.uvicorn.dev/" class="external-link" target="_blank">Uvicorn</a>: 高性能な ASGI サーバー。
* <a href="https://hypercorn.readthedocs.io/" class="external-link" target="_blank">Hypercorn</a>: HTTP/2 や Trio に対応する ASGI サーバーなど。
* <a href="https://github.com/django/daphne" class="external-link" target="_blank">Daphne</a>: Django Channels のために作られた ASGI サーバー。
* <a href="https://github.com/emmett-framework/granian" class="external-link" target="_blank">Granian</a>: Python アプリケーション向けの Rust 製 HTTP サーバー。
* <a href="https://unit.nginx.org/howto/fastapi/" class="external-link" target="_blank">NGINX Unit</a>: 軽量で多用途な Web アプリケーションランタイム。
## サーバーマシンとサーバープログラム { #server-machine-and-server-program }
名称に関する小さな注意点があります。💡
「サーバー」という言葉は、リモート/クラウド上のコンピュータ(物理/仮想マシン)と、そのマシン上で動作しているプログラム(例: Uvicornの両方を指すのに一般的に使われます。
一般に「サーバー」と書かれているときは、そのどちらかを指している可能性があることを覚えておいてください。
リモートマシンを指す場合、「サーバー」のほか「マシン」「VM仮想マシン」「ード」などとも呼ばれます。いずれも通常 Linux を実行し、そこでプログラムを動かすリモートマシンを指します。
## サーバープログラムをインストール { #install-the-server-program }
FastAPI をインストールすると、本番サーバーの Uvicorn が同梱されており、`fastapi run` コマンドで起動できます。
ただし、ASGI サーバーを手動でインストールすることもできます。
[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成して有効化し、サーバーアプリケーションをインストールしてください。
例として、Uvicorn をインストールするには:
<div class="termy">
@ -18,37 +88,21 @@ $ pip install "uvicorn[standard]"
</div>
////
他の ASGI サーバープログラムでも同様の手順です。
/// tip | 豆知識
`standard`加えることで、Uvicornがインストールされ、いくつかの推奨される依存関係を利用するようになります。
`standard`付けると、Uvicorn は推奨の追加依存関係もインストールして使用します。
これには、`asyncio` の高性能な完全互換品である `uvloop` が含まれ、並行処理のパフォーマンスが大幅に向上します。
その中には、`asyncio` の高性能なドロップイン代替であり、大きな並行実行性能の向上をもたらす `uvloop` も含まれます。
`pip install "fastapi[standard]"` のように FastAPI をインストールした場合は、すでに `uvicorn[standard]` も含まれます。
///
//// tab | Hypercorn
## サーバープログラムを起動 { #run-the-server-program }
* <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>, HTTP/2にも対応しているASGIサーバ。
<div class="termy">
```console
$ pip install hypercorn
---> 100%
```
</div>
...または、これら以外のASGIサーバ。
////
そして、チュートリアルと同様な方法でアプリケーションを起動して下さい。ただし、以下の様に`--reload` オプションは使用しないで下さい:
//// tab | Uvicorn
ASGI サーバーを手動でインストールした場合、通常は FastAPI アプリケーションをインポートさせるために、特別な形式のインポート文字列を渡す必要があります:
<div class="termy">
@ -60,26 +114,44 @@ $ uvicorn main:app --host 0.0.0.0 --port 80
</div>
////
/// note | 備考
//// tab | Hypercorn
`uvicorn main:app` というコマンドは次を指します:
<div class="termy">
* `main`: ファイル `main.py`Python の「モジュール」)。
* `app`: `main.py` 内で `app = FastAPI()` により作成されたオブジェクト。
```console
$ hypercorn main:app --bind 0.0.0.0:80
これは次と等価です:
Running on 0.0.0.0:8080 over http (CTRL + C to quit)
```Python
from main import app
```
</div>
///
////
他の ASGI サーバープログラムでも同様のコマンドがあり、詳細はそれぞれのドキュメントを参照してください。
停止した場合に自動的に再起動させるツールを設定したいかもしれません。
/// warning | 注意
さらに、<a href="https://gunicorn.org/" class="external-link" target="_blank">Gunicorn</a>をインストールして<a href="https://www.uvicorn.dev/#running-with-gunicorn" class="external-link" target="_blank">Uvicornのマネージャーとして使用したり</a>、複数のワーカーでHypercornを使用したいかもしれません
Uvicorn などのサーバーは、開発時に便利な `--reload` オプションをサポートしています
ワーカー数などの微調整も行いたいかもしれません
しかし `--reload` は多くのリソースを消費し、不安定になるなどの性質があります
しかしこれら全てをやろうとすると、自動的にこれらを行うDockerイメージを使う方が楽かもしれません。
開発中には非常に役立ちますが、 本番環境では使用すべきではありません。
///
## デプロイの概念 { #deployment-concepts }
これらの例は、サーバープログラム(例: Uvicornを実行し、事前に決めたポート例: `80`)で、すべての IP`0.0.0.0`)をリッスンする「単一プロセス」を起動します。
これが基本的な考え方です。ただし、次のような追加事項にも対応したくなるでしょう:
* セキュリティ - HTTPS
* 起動時に実行
* 再起動
* レプリケーション(実行プロセス数)
* メモリ
* 起動前の事前ステップ
これらの各概念についての考え方や、対処するための具体例・戦略を次の章で説明します。🚀

View File

@ -153,7 +153,7 @@ Hello World from Python
/// tip | 豆知識
詳しくは <a href="https://12factor.net/config" class="external-link" target="_blank">The Twelve-Factor App: Config</a> を参照してください。
詳しくは <a href="https://12factor.net/config" class="external-link" target="_blank">The Twelve-Factor App: 設定</a> を参照してください。
///
@ -291,7 +291,7 @@ $ C:\opt\custompython\bin\python
これで、**環境変数**とは何か、Pythonでどのように使用するかについて、基本的な理解が得られたはずです。
環境変数についての詳細は、<a href="https://en.wikipedia.org/wiki/Environment_variable" class="external-link" target="_blank">Wikipedia for Environment Variable</a> も参照してください。
環境変数についての詳細は、<a href="https://en.wikipedia.org/wiki/Environment_variable" class="external-link" target="_blank">Wikipedia の環境変数</a> も参照してください。
多くの場合、環境変数がどのように役立ち、すぐに適用できるのかはあまり明確ではありません。しかし、開発中のさまざまなシナリオで何度も登場するため、知っておくとよいでしょう。

View File

@ -0,0 +1,75 @@
# FastAPI CLI { #fastapi-cli }
**FastAPI CLI** は、FastAPI アプリの提供、FastAPI プロジェクトの管理などに使用できるコマンドラインプログラムです。
FastAPI をインストールすると(例: `pip install "fastapi[standard]"`)、`fastapi-cli` というパッケージが含まれます。このパッケージがターミナルで使用する `fastapi` コマンドを提供します。
開発用に FastAPI アプリを起動するには、`fastapi dev` コマンドを使用できます:
<div class="termy">
```console
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
<span style="background-color:#009485"><font color="#D3D7CF"> FastAPI </font></span> Starting development server 🚀
Searching for package file structure from directories with
<font color="#3465A4">__init__.py</font> files
Importing from <font color="#75507B">/home/user/code/</font><font color="#AD7FA8">awesomeapp</font>
<span style="background-color:#007166"><font color="#D3D7CF"> module </font></span> 🐍 main.py
<span style="background-color:#007166"><font color="#D3D7CF"> code </font></span> Importing the FastAPI app object from the module with the
following code:
<u style="text-decoration-style:solid">from </u><u style="text-decoration-style:solid"><b>main</b></u><u style="text-decoration-style:solid"> import </u><u style="text-decoration-style:solid"><b>app</b></u>
<span style="background-color:#007166"><font color="#D3D7CF"> app </font></span> Using import string: <font color="#3465A4">main:app</font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Server started at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> server </font></span> Documentation at <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
<span style="background-color:#007166"><font color="#D3D7CF"> tip </font></span> Running in development mode, for production use:
<b>fastapi run</b>
Logs:
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Will watch for changes in these directories:
<b>[</b><font color="#4E9A06">&apos;/home/user/code/awesomeapp&apos;</font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Uvicorn running on <font color="#729FCF"><u style="text-decoration-style:solid">http://127.0.0.1:8000</u></font> <b>(</b>Press CTRL+C to
quit<b>)</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><font color="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Started server process <b>[</b><font color="#34E2E2"><b>383153</b></font><b>]</b>
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Waiting for application startup.
<span style="background-color:#007166"><font color="#D3D7CF"> INFO </font></span> Application startup complete.
```
</div>
`fastapi` というコマンドラインプログラムが **FastAPI CLI** です。
FastAPI CLI は、Python プログラムへのパス(例: `main.py`)を受け取り、`FastAPI` インスタンス(通常は `app`)を自動検出し、適切な import 方法を判断して提供します。
本番環境では代わりに `fastapi run` を使用します。🚀
内部的には、**FastAPI CLI** は <a href="https://www.uvicorn.dev" class="external-link" target="_blank">Uvicorn</a>(高性能で本番運用向けの ASGI サーバー)を使用します。😎
## `fastapi dev` { #fastapi-dev }
`fastapi dev` を実行すると、開発モードが有効になります。
デフォルトでは、**auto-reload** が有効です。コードを変更するとサーバーが自動で再読み込みされます。これはリソースを多く消費し、無効時より安定性が低くなる可能性があります。開発時のみに使用してください。また、IP アドレス `127.0.0.1`(マシン自身のみと通信するための IP、`localhost`)で待ち受けます。
## `fastapi run` { #fastapi-run }
`fastapi run` を実行すると、デフォルトで本番モードで起動します。
デフォルトでは、**auto-reload** は無効です。また、IP アドレス `0.0.0.0`(利用可能なすべての IP アドレスを意味します)で待ち受けるため、そのマシンと通信できる任意のクライアントから公開アクセスが可能になります。これは、たとえばコンテナ内など、本番環境で一般的な実行方法です。
多くの場合(そして推奨されるのは)、上位に HTTPS を終端する「termination proxy」を置きます。これはアプリのデプロイ方法に依存し、プロバイダが代行する場合もあれば、自分で設定する必要がある場合もあります。
/// tip | 豆知識
詳しくは、[デプロイのドキュメント](deployment/index.md){.internal-link target=_blank}を参照してください。
///

View File

@ -1,54 +1,55 @@
# 機能
# 機能 { #features }
## FastAPIの機能
## FastAPIの機能 { #fastapi-features }
**FastAPI** は以下の機能をもちます:
**FastAPI** は次のものを提供します:
### オープンスタンダード準拠
### オープンスタンダード準拠 { #based-on-open-standards }
* API作成のための<a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a>これは、<abbr title="also known as: endpoints, routes">path</abbr> <abbr title="also known as HTTP methods, as POST, GET, PUT, DELETE">operations</abbr>の宣言、パラメータ、ボディリクエスト、セキュリティなどを含んでいます。
* <a href="http://json-schema.org/" class="external-link" target="_blank"><strong>JSONスキーマ</strong></a>を使用したデータモデルのドキュメント自動生成OpenAPIはJSONスキーマに基づいている)。
* 綿密な調査の結果、上層に後付けするのではなく、これらの基準に基づいて設計されました
* API 作成のための <a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank"><strong>OpenAPI</strong></a><dfn title="別名: エンドポイント、ルート">path</dfn> <dfn title="別名: HTTP メソッドPOST、GET、PUT、DELETE など)">operations</dfn>、パラメータ、リクエストボディ、セキュリティなどの宣言を含みます。
* <a href="https://json-schema.org/" class="external-link" target="_blank"><strong>JSON Schema</strong></a> によるデータモデルの自動ドキュメント化OpenAPI 自体が JSON Schema に基づいています)。
* 入念な調査のうえ、これらの標準を中心に設計されています。後付けのレイヤーではありません
* これにより、多くの言語で自動 **クライアントコード生成** が可能です。
### 自動ドキュメント生成
対話的なAPIドキュメントと探索的なwebユーザーインターフェースを提供します。フレームワークはOpenAPIを基にしているため、いくつかのオプションがあり、デフォルトで2つ含まれています。
### 自動ドキュメント { #automatic-docs }
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>で、インタラクティブな探索をしながら、ブラウザから直接APIを呼び出してテストが行えます。
対話的な API ドキュメントと探索的な Web ユーザーインターフェース。フレームワークは OpenAPI に基づいているため、複数のオプションがあり、デフォルトで 2 つ含まれます。
* <a href="https://github.com/swagger-api/swagger-ui" class="external-link" target="_blank"><strong>Swagger UI</strong></a>。インタラクティブに探索しつつ、ブラウザから直接 API を呼び出してテストできます。
![Swagger UI interaction](https://fastapi.tiangolo.com/img/index/index-03-swagger-02.png)
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a>を使用したもう一つのAPIドキュメント生成
* <a href="https://github.com/Rebilly/ReDoc" class="external-link" target="_blank"><strong>ReDoc</strong></a> による代替の API ドキュメント
![ReDoc](https://fastapi.tiangolo.com/img/index/index-06-redoc-02.png)
### 現代的なPython
### 現代的なPythonのみ { #just-modern-python }
FastAPIの機能はすべて、標準のPython 3.8型宣言に基づいていますPydanticの功績。新しい構文はありません。ただの現代的な標準のPythonです。
すべて標準の **Python の型** 宣言Pydantic に感謝)に基づいています。新しい構文を学ぶ必要はありません。標準的でモダンな Python だけです。
FastAPIを使用しない場合でもPythonの型の使用方法について簡単な復習が必要な場合は、短いチュートリアル[Python Types](python-types.md){.internal-link target=_blank}を参照してください。
FastAPI を使わない場合でもPython の型の使い方を 2 分で復習したい場合は、短いチュートリアル [Python Types](python-types.md){.internal-link target=_blank} を参照してください。
型を使用した標準的なPythonを記述します:
型を使った標準的な Python を記述します:
```Python
from datetime import date
from pydantic import BaseModel
# Declare a variable as a str
# and get editor support inside the function
# 変数を str として宣言
# そして関数内でエディタ支援を受ける
def main(user_id: str):
return user_id
# A Pydantic model
# Pydantic モデル
class User(BaseModel):
id: int
name: str
joined: date
```
これは以下のように用いられます:
これは次のように使えます:
```Python
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
@ -62,143 +63,139 @@ second_user_data = {
my_second_user: User = User(**second_user_data)
```
/// info | 情報
/// info
`**second_user_data`以下を意味します:
`**second_user_data`次の意味です:
`second_user_data`辞書のキーと値を直接、キーと値の引数として渡します。これは、`User(id=4, name="Mary", joined="2018-11-30")`と同等です。
`second_user_data` 辞書のキーと値を、そのままキーバリュー引数として渡します。これは `User(id=4, name="Mary", joined="2018-11-30")` と同等です。
///
### エディタのサポート
### エディタのサポート { #editor-support }
すべてのフレームワークは使いやすく直感的に使用できるように設計されており、すべての決定は開発を開始する前でも複数のエディターでテストされ、最高の開発体験が保証されます。
フレームワーク全体が使いやすく直感的になるよう設計されており、最高の開発体験を確保するため、開発開始前から複数のエディタであらゆる判断が検証されています。
前回のPython開発者調査では、<a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">最も使用されている機能が「オートコンプリート」であることが明らかになりました。</a>
Python 開発者調査では、<a href="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features" class="external-link" target="_blank">最もよく使われる機能の 1 つが「オートコンプリート」であることが明らかです</a>
**FastAPI** フレームワークは、この要求を満たすことを基本としています。オートコンプリートはどこでも機能します。
**FastAPI** はその要求を満たすことを基盤にしています。オートコンプリートはどこでも機能します。
ドキュメントに戻る必要はほとんどありません。
エディターがどのように役立つかを以下に示します:
エディタがどのように役立つかの例です:
* <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a>の場合:
* <a href="https://code.visualstudio.com/" class="external-link" target="_blank">Visual Studio Code</a> の場合:
![editor support](https://fastapi.tiangolo.com/img/vscode-completion.png)
* <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>の場合:
* <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> の場合:
![editor support](https://fastapi.tiangolo.com/img/pycharm-completion.png)
以前は不可能だと考えていたコードでさえ補完されます。例えば、リクエストからのJSONボディネストされている可能性がある内の `price`キーです。
以前は不可能だと思っていたコードでも補完が得られます。例えば、リクエストから届くネストされている可能性のあるJSON ボディ内の `price` キーなどです。
間違ったキー名を入力したり、ドキュメントを行き来したり、上下にスクロールして`username`と`user_name`のどちらを使用したか調べたりする必要はもうありません。
もう間違ったキー名を入力したり、ドキュメントを行き来したり、上下にスクロールして最終的に `username``user_name` のどちらを使ったのか探す必要はありません。
### 簡潔
### 簡潔 { #short }
すべてに適切な**デフォルト**があり、オプションの構成ができます。必要なことを実行し、必要なAPIを定義するためにすべてのパラメーターを調整できます。
すべてに妥当な **デフォルト** があり、どこでもオプションで構成できます。必要に応じてすべてのパラメータを微調整して、求める API を定義できます。
ただし、デフォルトでもすべて **うまくいきます**。
しかしデフォルトのままでも、すべて **うまく動きます**。
### 検証
### 検証 { #validation }
* 以下の様な、ほとんどのすべてのPython **データ型**の検証:
* JSONオブジェクト`dict`
* 項目の型を定義するJSON配列`list`
* 最小長と最大長のある文字列(`str`)フィールド
* 最小値と最大値のある数値(`int`、` float`
* ほとんど(あるいはすべて?)の Python の **データ型** に対する検証:
* JSON オブジェクト(`dict`
* 項目の型を定義する JSON 配列(`list`
* 文字列(`str`)フィールドの最小/最大長。
* 数値(`int`、`float`の最小/最大値、など。
* よりエキゾチックな型の検証
* URL
* Eメール
* UUID
* ...その他
* よりエキゾチックな型の検証:
* URL
* Email。
* UUID
* ...その他
すべての検証は、確立され堅牢な **Pydantic** によって処理されます。
すべての検証は、確立され堅牢な **Pydantic** によって処理されます。
### セキュリティと認証
### セキュリティと認証 { #security-and-authentication }
セキュリティと認証が統合されています。 データベースまたはデータモデルについても妥協していません。
セキュリティと認証が統合されています。データベースやデータモデルとの妥協はありません。
以下のOpenAPIで定義されているすべてのセキュリティスキームを含む:
OpenAPI で定義されたすべてのセキュリティスキームをサポートします:
* HTTPベーシック
* **OAuth2****JWTトークン**も使用)。 JWTを使用したOAuth2のチュートリアル[OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}を確認してください。
* APIキー:
* ヘッダー
* クエリパラメータ
* クッキー、等
* HTTP Basic。
* **OAuth2****JWT トークン** も可)。チュートリアル [JWT を用いた OAuth2](tutorial/security/oauth2-jwt.md){.internal-link target=_blank} を確認してください。
* API キー(以下の場所):
* ヘッダー
* クエリパラメータ
* クッキー、など。
さらに、Starletteのすべてのセキュリティ機能も含みます**セッションCookie**を含む)。
さらに、Starlette のすべてのセキュリティ機能(**セッション Cookie** を含む)も利用できます
これらは、システム、データストア、リレーショナルデータベース、NoSQLデータベースなどと簡単に統合できる再利用可能なツールとコンポーネントとして構築されています。
これらはすべて再利用可能なツールやコンポーネントとして構築されており、システム、データストア、リレーショナル/NoSQL データベース等と容易に統合できます。
### 依存性の注入Dependency Injection
### 依存性の注入 { #dependency-injection }
FastAPIには非常に使いやすく、非常に強力な<abbr title='also known as "components", "resources", "services", "providers"'><strong>依存性の注入</strong></abbr>システムを備えています。
FastAPI には、非常に使いやすく、かつ非常に強力な <dfn title='別名: コンポーネント、リソース、サービス、プロバイダー'><strong>依存性の注入</strong></dfn> システムがあります。
* 依存関係でさえも依存関係を持つことができ、階層または **依存関係の"グラフ"** を作成することができます。
* 依存関係は依存関係を持つこともでき、階層または **依存関係の「グラフ」** を作成できます。
* すべてフレームワークによって**自動的に処理**されます。
* すべての依存関係はリクエストからデータを要求でき、*path operation* の制約と自動ドキュメントを**拡張**できます。
* 依存関係で定義された *path operation* のパラメータについても**自動検証**されます。
* 複雑なユーザー認証システム、**データベース接続** などのサポート。
* **データベースやフロントエンド等との妥協は不要**。すべてと簡単に統合できます。
* フレームワークによってすべて**自動的に処理**されます。
* すべての依存関係はリクエストからのデータを要請できて、**path operationsの制約と自動ドキュメンテーションを拡張できます**。
* 依存関係で定義された *path operation* パラメータも**自動検証**が可能です。
* 複雑なユーザー認証システム、**データベース接続**などのサポート
* **データベース、フロントエンドなどに対する妥協はありません**。それらすべてと簡単に統合できます。
### 無制限の「プラグイン」 { #unlimited-plug-ins }
### 無制限の「プラグイン」
別の言い方をすれば、プラグインは不要で、必要なコードをインポートして使うだけです。
他の方法では、それらを必要とせず、必要なコードをインポートして使用します。
あらゆる統合は(依存関係を用いて)非常に簡単に使えるよう設計されており、*path operation* で使うのと同じ構造と構文で、2 行のコードでアプリケーション用の「プラグイン」を作れます。
統合は非常に簡単に使用できるように設計されており(依存関係を用いて)、*path operations* で使用されているのと同じ構造と構文を使用して、2行のコードでアプリケーションの「プラグイン」を作成できます。
### テスト済み { #tested }
* 100% の <dfn title="自動的にテストされるコードの量">テストカバレッジ</dfn>
* 100% <dfn title="Python の型アノテーション。これにより、エディタや外部ツールからより良い支援が受けられます">型アノテーション付き</dfn>のコードベース。
* 本番アプリケーションで使用されています。
### テスト
## Starletteの機能 { #starlette-features }
* <abbr title = "自動的にテストされるコードの量">テストカバレッジ</abbr> 100%
* <abbr title = "Python型アテーション。これにより、ユーザーはより良いエディターと外部ツールのサポート受けられる。">型アノテーション</abbr>100%のコードベース
* 本番アプリケーションで使用されます
**FastAPI** は <a href="https://www.starlette.dev/" class="external-link" target="_blank"><strong>Starlette</strong></a> と完全に互換性があり(かつそれに基づいています)。そのため、手元の Starlette の追加コードも動作します。
## Starletteの機能
`FastAPI` は実際には `Starlette` のサブクラスです。すでに Starlette を知っている、あるいは使っているなら、ほとんどの機能は同じように動作します。
**FastAPI**は、<a href="https://www.starlette.dev/" class="external-link" target="_blank"><strong>Starlette </strong></a>と完全に互換性がありますそしてベースになっています。したがって、追加のStarletteコードがあれば、それも機能します。
**FastAPI** では **Starlette** のすべての機能が利用できますFastAPI は強化された Starlette にすぎません):
`FastAPI`は実際には`Starlette`のサブクラスです。したがって、Starletteをすでに知っているか使用している場合は、ほとんどの機能が同じように機能します。
**FastAPI**を使用すると、以下のような、**Starlette**のすべての機能を利用できますFastAPIはStarletteを強化したものにすぎないため:
* 見事なパフォーマンス。<a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank"> **NodeJS**および**Go**に匹敵する、最速のPythonフレームワークの1つです。</a>
* **WebSocket**のサポート
* **GraphQL**のサポート
* プロセス内バックグラウンドタスク
* 起動およびシャットダウンイベント
* `httpx`に基づいて構築されたテストクライアント
* **CORS**、GZip、静的ファイル、ストリーミング応答
* **セッションとCookie**のサポート
* テストカバレッジ100%
* 型アテーション100%のコードベース
## Pydanticの特徴
**FastAPI**は<a href="https://docs.pydantic.dev/" class="external-link" target="_blank"><strong>Pydantic </strong></a>と完全に互換性がありますそしてベースになっています。したがって、追加のPydanticコードがあれば、それも機能します。
データベースのために<abbr title = "Object-Relational Mapper">ORM</abbr>sや、<abbr title = "Object-Document Mapper">ODM</abbr>sなどの、Pydanticに基づく外部ライブラリを備えています。
これは、すべてが自動的に検証されるため、多くの場合、リクエストから取得したオブジェクトを**データベースに直接**渡すことができるということを意味しています。
同じことがその逆にも当てはまり、多くの場合、データベースから取得したオブジェクトを**クライアントに直接**渡すことができます。
**FastAPI**を使用すると、**Pydantic**のすべての機能を利用できますFastAPIがPydanticに基づいてすべてのデータ処理を行っているため
* **brainfuckなし**
* スキーマ定義のためのマイクロ言語を新たに学習する必要はありません。
* Pythonの型を知っている場合は、既にPydanticの使用方法を知っているに等しいです。
* ユーザーの **<abbr title = "コードエディターに似た統合開発環境">IDE</abbr>/<abbr title = "コードエラーをチェックするプログラム">リンター</abbr>/思考 とうまく連携します**
* Pydanticのデータ構造は、ユーザーが定義するクラスの単なるインスタンスであるため、オートコンプリート、リンティング、mypy、およびユーザーの直感はすべて、検証済みのデータで適切に機能するはずです。
* **複雑な構造**を検証:
* 階層的なPydanticモデルや、Pythonの「`typing`」の「`list`」と「`dict`」などの利用。
* バリデーターにより、複雑なデータスキーマを明確かつ簡単に定義、チェックし、JSONスキーマとして文書化できます。
* 深く**ネストされたJSON**オブジェクトを作成し、それらすべてを検証してアノテーションを付けることができます。
* **拡張可能**
* Pydanticでは、カスタムデータ型を定義できます。または、バリデーターデコレーターで装飾されたモデルのメソッドを使用して検証を拡張できます。
* 圧倒的なパフォーマンス。<a href="https://github.com/encode/starlette#performance" class="external-link" target="_blank">利用可能な最速クラスの Python フレームワークの 1 つで、**NodeJS** や **Go** と同等です</a>
* **WebSocket** のサポート。
* プロセス内バックグラウンドタスク。
* 起動およびシャットダウンイベント。
* HTTPX に基づくテストクライアント。
* **CORS**、GZip、静的ファイル、ストリーミングレスポンス。
* **セッションと Cookie** のサポート。
* テストカバレッジ 100%。
* 型アノテーション 100% のコードベース。
## Pydanticの機能 { #pydantic-features }
**FastAPI** は <a href="https://docs.pydantic.dev/" class="external-link" target="_blank"><strong>Pydantic</strong></a> と完全に互換性があり(かつそれに基づいています)。そのため、手元の Pydantic の追加コードも動作します。
Pydantic に基づく外部ライブラリ(データベース用の <abbr title="Object-Relational Mapper - オブジェクト関係マッパー">ORM</abbr><abbr title="Object-Document Mapper - オブジェクトドキュメントマッパー">ODM</abbr> など)も含まれます。
これは、すべてが自動的に検証されるため、多くの場合、リクエストから取得したオブジェクトを **そのままデータベースに** 渡せることを意味します。
逆方向も同様で、多くの場合、データベースから取得したオブジェクトを **そのままクライアントに** 渡せます。
**FastAPI** では **Pydantic** のすべての機能が利用できますFastAPI はデータ処理のすべてで Pydantic に基づいています):
* **brainfuck なし**
* スキーマ定義のための新しいマイクロ言語を学ぶ必要はありません。
* Python の型を知っていれば、Pydantic の使い方もわかります。
* **<abbr title="Integrated Development Environment - 統合開発環境: コードエディタに類似">IDE</abbr>/<dfn title="コードのエラーを検査するプログラム">リンター</dfn>/思考** と気持ちよく連携します:
* Pydantic のデータ構造は、あなたが定義するクラスの単なるインスタンスなので、オートコンプリート、リンティング、mypy、そしてあなたの直感が、検証済みデータに対して適切に機能します。
* **複雑な構造** を検証:
* 階層的な Pydantic モデルや、Python の `typing` にある `List``Dict` などを利用できます。
* さらにバリデータにより、複雑なデータスキーマを明確かつ容易に定義・検査でき、JSON Schema として文書化できます。
* 深く **ネストされた JSON** オブジェクトを扱え、それらすべてを検証してアノテーションを付与できます。
* **拡張可能**
* Pydantic ではカスタムデータ型を定義できますし、バリデータデコレーターで装飾したモデルメソッドで検証を拡張できます。
* テストカバレッジ 100%。

View File

@ -1,101 +1,255 @@
# FastAPIを応援 - ヘルプの入手
# FastAPIを応援 - ヘルプの入手 { #help-fastapi-get-help }
**FastAPI** は気に入りましたか?
FastAPIやユーザーや開発者を応援したいですか?
FastAPIや他のユーザー、作者を応援したいですか?
しくは、 **FastAPI** についてヘルプが必要ですか?
それと**FastAPI** についてヘルプが必要ですか?
とても簡単に応援できます (ただ1、2回クリックするだけのものもあります)
とても簡単に応援できる方法があります1、2回クリックするだけのものもあります
また、ヘルプを入手する手段がいくつかあります。
ヘルプを得る方法もいくつかあります。
## GitHubで **FastAPI** にStar
## ニュースレターを購読 { #subscribe-to-the-newsletter }
GitHubでFastAPIに「Star」をつけることができます (右上部のStarボタンをクリック): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. ⭐️
[**FastAPI and friends** ニュースレター](newsletter.md){.internal-link target=_blank}(配信はまれです)を購読すると、次の情報をキャッチアップできます:
スターを増やすことで、他のユーザーの目につきやすくなり、多くの人にとって便利なものであることを示せます。
* FastAPI と関連プロジェクトのニュース 🚀
* ガイド 📝
* 機能 ✨
* 互換性に影響する変更 🚨
* ヒントやコツ ✅
## GitHubレポジトリのリリースをWatch
## X (Twitter) で FastAPI をフォロー { #follow-fastapi-on-x-twitter }
GitHubでFastAPIを「Watch」できます (右上部のWatchボタンをクリック): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. 👀
<a href="https://x.com/fastapi" class="external-link" target="_blank">**X (Twitter)** で @fastapi をフォロー</a>して、**FastAPI** の最新情報を受け取りましょう。🐦
## GitHubで **FastAPI** にStar { #star-fastapi-in-github }
GitHubでFastAPIに「Star」をつけることができます右上部のStarボタンをクリック: <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>。⭐️
スターを増やすことで、他のユーザーの目につきやすくなり、すでに多くの人の役に立っていることが伝わります。
## GitHubレポジトリのリリースをWatch { #watch-the-github-repository-for-releases }
GitHubでFastAPIを「Watch」できます右上部の「Watch」ボタンをクリック: <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>。👀
そこで「Releases only」を選択できます。
これを行うと、**FastAPI** バグ修正や新機能の実装などの新しいリリース (新しいバージョン) があるたびに (メールで) 通知を受け取れます。
これを行うと、バグ修正や新機能を含む **FastAPI** の新しいリリース(新バージョン)があるたびに、(メールで)通知を受け取れます。
## 開発者とつながる
## 開発者とつながる { #connect-with-the-author }
以下で、<a href="https://tiangolo.com" class="external-link" target="_blank">開発者 (Sebastián Ramírez / `tiangolo`)</a> とコンタクトをとれます:
作者である<a href="https://tiangolo.com" class="external-link" target="_blank">Sebastián Ramírez / `tiangolo`</a>とつながれます。
できること:
* <a href="https://github.com/tiangolo" class="external-link" target="_blank">**GitHub** でフォロー</a>
* 他のオープンソースプロジェクトを確認できます。何かの助けになるものが見つかるかもしれません。
* 新たなオープンソースプロジェクトを作成したときに通知されます。
* <a href="https://x.com/tiangolo" class="external-link" target="_blank">**X (Twitter)** でフォロー</a>
* FastAPIの使用用途を教えてください (聞いてみたいです)。
* 新たなツールの発表やリリースが聞けます。
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">**Linkedin** でつながる</a>
* 新たなツールの発表やリリースが聞けます (ただしX (Twitter)の方が利用頻度が高いですが 🤷‍♂)。
* <a href="https://dev.to/tiangolo" class="external-link" target="_blank">**Dev.to**</a><a href="https://medium.com/@tiangolo" class="external-link" target="_blank">**Medium**</a> で著作物を読む (またはフォロー)。
* アイデアや作成ツールについての記事が読めます。
* 新規記事の執筆を通知してくれます。
* 役に立つかもしれない、私が作成した他のオープンソースプロジェクトを見られます。
* 新しいオープンソースプロジェクトを作成したときにわかります。
* <a href="https://x.com/tiangolo" class="external-link" target="_blank">**X (Twitter)** でフォロー</a> または <a href="https://fosstodon.org/@tiangolo" class="external-link" target="_blank">Mastodon</a>
* あなたがどのようにFastAPIを使っているか教えてください聞けると嬉しいです
* 新しいツールの告知やリリースを聞けます。
* さらに、<a href="https://x.com/fastapi" class="external-link" target="_blank">X (Twitter) の @fastapi</a>(別アカウント)もフォローできます。
* <a href="https://www.linkedin.com/in/tiangolo/" class="external-link" target="_blank">**LinkedIn** でフォロー</a>
* 新しいツールの告知やリリースを聞けますただしX (Twitter) の方をよく使っています 🤷‍♂)。
* <a href="https://dev.to/tiangolo" class="external-link" target="_blank">**Dev.to**</a><a href="https://medium.com/@tiangolo" class="external-link" target="_blank">**Medium**</a> で執筆内容を読む(またはフォロー)。
* 私のアイデアや、作成したツールに関する記事を読めます。
* 新しい記事を公開したときに読めます。
## **FastAPI**関するツイート
## **FastAPI**ついてツイート { #tweet-about-fastapi }
<a href="https://x.com/compose/tweet?text=I'm loving FastAPI because... https://github.com/fastapi/fastapi cc @tiangolo" class="external-link" target="_blank">**FastAPI** についてツイート</a>、開発者や他の人にどこが気に入ったのか教えてください。🎉
<a href="https://x.com/compose/tweet?text=I'm loving @fastapi because... https://github.com/fastapi/fastapi" class="external-link" target="_blank">**FastAPI** についてツイート</a>て、なぜ気に入っているのかを私や他の人に教えてください。🎉
**FastAPI** がどのように使われ、どこが気に入られ、どんなプロジェクト/会社で使われているかなどについて知りたいです。
**FastAPI** がどのように使われているか、どこを気に入っているか、どのプロジェクト/会社で使っているか等、聞けると嬉しいです。
## FastAPIに投票
## FastAPIに投票 { #vote-for-fastapi }
* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Slantで **FastAPI** に投票</a>
* <a href="https://alternativeto.net/software/fastapi/" class="external-link" target="_blank">AlternativeToで **FastAPI** に投票</a>
* <a href="https://github.com/marmelab/awesome-rest/pull/93" class="external-link" target="_blank">awesome-restで **FastAPI** に投票</a>
* <a href="https://www.slant.co/options/34241/~fastapi-review" class="external-link" target="_blank">Slantで **FastAPI** に投票</a>
* <a href="https://alternativeto.net/software/fastapi/about/" class="external-link" target="_blank">AlternativeToで **FastAPI** に投票</a>
* <a href="https://stackshare.io/pypi-fastapi" class="external-link" target="_blank">StackShare で **FastAPI** を使っていると宣言</a>
## GitHub issuesで他の人を助ける
## GitHubで質問に困っている人を助ける { #help-others-with-questions-in-github }
<a href="https://github.com/fastapi/fastapi/issues" class="external-link" target="_blank">既存のissues</a>を確認して、他の人を助けてみてください。皆さんが回答を知っているかもしれない質問がほとんどです。🤓
次の場所で、他の人の質問を手助けできます:
## GitHubレポジトリをWatch
* <a href="https://github.com/fastapi/fastapi/discussions/categories/questions?discussions_q=category%3AQuestions+is%3Aunanswered" class="external-link" target="_blank">GitHub Discussions</a>
* <a href="https://github.com/fastapi/fastapi/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Aquestion+-label%3Aanswered+" class="external-link" target="_blank">GitHub Issues</a>
GitHubでFastAPIを「watch」できます (右上部の「watch」ボタンをクリック): <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>. 👀
多くの場合、その質問の答えをすでに知っているかもしれません。🤓
「Releases only」ではなく「Watching」を選択すると、新たなissueが立てられた際に通知されます。
もし多くの人の質問に答えて助けてくれたなら、あなたは公式の[FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank}になります。🎉
そして、issueを解決し他の人を助けることができます。
最も大事なポイントは「親切であること」を心がけることです。人はフラストレーションを抱えてやって来るので、必ずしも最良の聞き方をしているとは限りませんが、できる限り親切に対応しましょう。🤗
## issuesを立てる
**FastAPI** コミュニティは親切で歓迎的であることを目指しています。同時に、いじめや他者への無礼な振る舞いは受け入れないでください。お互いを大事にしましょう。
GitHubレポジトリで<a href="https://github.com/fastapi/fastapi/issues/new/choose" class="external-link" target="_blank">新たなissueを立てられます</a>。例えば:
---
* 質問、または、問題の報告
* 新機能の提案
以下はDiscussions や Issues で)他の人の質問を手助けする方法です:
**Note**: issueを立てた人は、他の人の手助けもお願いします。😉
### 質問を理解する { #understand-the-question }
## プルリクエストをする
* 質問者の「目的」やユースケースを理解できるか確認します。
以下の様な<a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">プルリクエストを作成</a>できます:
* 次に、質問(大半は質問です)が「明確」か確認します。
* ドキュメントのタイプミスを修正。
* 新たなドキュメントセクションを提案。
* 既存のissue/バグを修正。
* 新機能を追加。
* 多くの場合、ユーザーが想像した解決策についての質問になっていますが、もっと「良い」方法があるかもしれません。問題やユースケースをよりよく理解できれば、より良い「代替解決策」を提案できるかもしれません。
## 開発者のスポンサーになる
* 質問が理解できない場合は、さらに「詳細」を尋ねます。
<a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub sponsors</a>を通して開発者を経済的にサポートできます。
### 問題を再現する { #reproduce-the-problem }
そこで、感謝の気持ちを伝えるためにコーヒー☕️を買うことができます 😄
多くのケースや質問は、その人の「元のコード」に関係しています
## FastAPIを強化するツールのスポンサーになる
しばしばコードの断片だけが共有されますが、それでは問題を「再現」するには不十分です。
ドキュメントで見たように、FastAPIはStarletteとPydanticという巨人の肩に乗っています。
* ローカルで同じエラーや挙動を確認できるように、またはユースケースをよりよく理解できるように、**コピー&ペースト**して実行できる<a href="https://stackoverflow.com/help/minimal-reproducible-example" class="external-link" target="_blank">最小の再現可能な例</a>の提供を依頼できます。
以下のスポンサーになることもできます:
* とても寛大な気分なら、問題の説明だけをもとに、あなた自身でそのような**例を作成**してみることもできます。ただし時間がかかる可能性が高いので、まずは問題の明確化を依頼した方が良い場合もあります。
* <a href="https://github.com/sponsors/samuelcolvin" class="external-link" target="_blank">Samuel Colvin (Pydantic)</a>
* <a href="https://github.com/sponsors/encode" class="external-link" target="_blank">Encode (Starlette, Uvicorn)</a>
### 解決策を提案する { #suggest-solutions }
* 質問を理解できたら、可能な**回答**を提示できます。
* 多くの場合、相手の「根本的な問題やユースケース」を理解することが重要です。相手が試している方法より良い解決方法があるかもしれないからです。
### クローズを依頼する { #ask-to-close }
もし相手が返信してきて、あなたが問題を解決できたなら、おめでとう、**あなたはヒーロー**です!🦸
* その場合、次のように依頼できます:
* GitHub Discussions: コメントを**回答**としてマークしてもらう。
* GitHub Issues: issue を**クローズ**してもらう。
## GitHubレポジトリをWatch { #watch-the-github-repository }
GitHubでFastAPIを「Watch」できます右上部の「Watch」ボタンをクリック: <a href="https://github.com/fastapi/fastapi" class="external-link" target="_blank">https://github.com/fastapi/fastapi</a>。👀
「Releases only」ではなく「Watching」を選択すると、新しい issue や質問が作成されたときに通知を受け取れます。新しい issue のみ、Discussions のみ、PR のみ、など通知対象を絞ることもできます。
その上で、そうした質問の解決を手助けできます。
## 質問する { #ask-questions }
GitHubレポジトリで<a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">新しい質問</a>を作成できます。例えば:
* **質問**をする、または**問題**について尋ねる。
* 新しい**機能**を提案する。
**Note**: もしそうするなら、他の人の手助けもお願いします。😉
## プルリクエストをレビュー { #review-pull-requests }
他の人からのプルリクエストのレビューを手伝ってもらえます。
ここでも、できる限り親切であるようにしてください。🤗
---
プルリクエストをレビューするときのポイントです:
### 問題を理解する { #understand-the-problem }
* まず、そのプルリクエストが解決しようとしている**問題を理解**してください。長めの議論が GitHub Discussion や issue にあるかもしれません。
* その問題は実は**別の方法**で解決でき、プルリクエスト自体が不要な場合もあります。その場合は、その提案や質問をしても良いでしょう。
### スタイルは気にしすぎない { #dont-worry-about-style }
* コミットメッセージのスタイルなどはあまり気にしなくて大丈夫です。私は squash and merge を使い、コミットを手動で調整します。
* スタイルルールについても心配無用です。自動化ツールがすでにチェックしています。
ほかにスタイルや一貫性の要件があれば、私から直接依頼しますし、必要な変更を上に積む形でコミットを追加します。
### コードを確認 { #check-the-code }
* コードを確認して読み、妥当かどうかを見て、**ローカルで実行**し、本当に問題を解決しているか確かめてください。
* そのうえで、それを行ったことを**コメント**で伝えてください。そうすれば、実際に確認してくれたとわかります。
/// info | 情報
残念ながら、承認が複数ついただけのPRを、そのまま信頼することはできません。
説明が魅力的なためか、3件、5件以上の承認がついていても、実際にPRを確認すると壊れていたり、バグがあったり、主張する問題を解決していなかったりすることが何度もありました。😅
ですので、実際にコードを読み、実行して確認し、それをコメントで知らせてもらえることが本当に重要です。🤓
///
* もしPRを簡素化できそうなら、その依頼をしても構いませんが、細かい点にこだわり過ぎる必要はありません。主観的な見方が多く私にもあります 🙈)、基本的な点に集中できるとより良いでしょう。
### テスト { #tests }
* PRに**テスト**があるか確認を手伝ってください。
* PR前はテストが**失敗**することを確認します。🚨
* そしてPR後にテストが**成功**することを確認します。✅
* 多くのPRにはテストがありません。テストの追加を**リマインド**したり、テストを**提案**したりできます。これは最も時間を消費する部分の一つで、大いに助けになります。
* 何を試したかもコメントしてください。そうすれば、確認してくれたことがわかります。🤓
## プルリクエストを作成 { #create-a-pull-request }
[貢献](contributing.md){.internal-link target=_blank}として、次のようにプルリクエストでソースコードに貢献できます:
* ドキュメントで見つけたタイポの修正。
* 自分が作成/発見した FastAPI に関する記事・動画・ポッドキャストを、<a href="https://github.com/fastapi/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">このファイルを編集</a>して共有。
* 該当セクションの先頭にリンクを追加してください。
* 自分の言語への[ドキュメント翻訳を手伝う](contributing.md#translations){.internal-link target=_blank}。
* 他の人が作成した翻訳のレビューも手伝えます。
* 新しいドキュメントセクションの提案。
* 既存のissue/バグの修正。
* テストを追加してください。
* 新機能の追加。
* テストを追加してください。
* 関連があればドキュメントも追加してください。
## FastAPIのメンテナンスを手伝う { #help-maintain-fastapi }
**FastAPI** のメンテナンスを手伝ってください!🤓
やることはたくさんあり、その多くは**あなた**にもできます。
今すぐできる主なタスクは次のとおりです:
* [GitHubで質問に困っている人を助ける](#help-others-with-questions-in-github){.internal-link target=_blank}(上のセクションを参照)。
* [プルリクエストをレビュー](#review-pull-requests){.internal-link target=_blank}(上のセクションを参照)。
この2つが**最も時間を消費**します。FastAPI のメンテナンス作業の中心です。
これを手伝ってもらえると、**FastAPIのメンテナンスに貢献**し、**より速く・より良く前進**できるようになります。🚀
## チャットに参加 { #join-the-chat }
👥 <a href="https://discord.gg/VQjSZaeJmf" class="external-link" target="_blank">Discord チャットサーバー</a> 👥 に参加し、FastAPI コミュニティのみんなと交流しましょう。
/// tip | 豆知識
質問は <a href="https://github.com/fastapi/fastapi/discussions/new?category=questions" class="external-link" target="_blank">GitHub Discussions</a> に投稿してください。そこなら[FastAPI Experts](fastapi-people.md#fastapi-experts){.internal-link target=_blank}から助けてもらえる可能性がずっと高いです。
チャットは一般的な会話のみに使いましょう。
///
### 質問でチャットを使わない { #dont-use-the-chat-for-questions }
チャットは「自由な会話」がしやすいため、一般的すぎて答えにくい質問になりがちです。そのため、回答が得られない可能性があります。
GitHub では、テンプレートが正しい形で質問を書くのを助けてくれるため、良い回答を得やすくなりますし、質問する前に自分で問題を解決できることもあります。さらにGitHubなら、時間がかかっても私が必ずすべてに回答できるようにできます。チャットでは私個人にはそれができません。😅
チャットでの会話はGitHubほど検索しやすくないため、質問と回答が会話に埋もれがちです。そして、[FastAPI Expert](fastapi-people.md#fastapi-experts){.internal-link target=_blank}になるためにカウントされるのはGitHub上の活動だけです。ですから、GitHubの方が注目を集めやすいでしょう。
一方で、チャットには数千人のユーザーがいるため、ほぼ常に誰かと会話できる可能性が高いです。😄
## 作者をスポンサー { #sponsor-the-author }
あなたの**製品/会社**が **FastAPI** に依存している、または関連しており、そのユーザーにリーチしたい場合は、<a href="https://github.com/sponsors/tiangolo" class="external-link" target="_blank">GitHub sponsors</a> を通じて作者(私)を支援できます。プランに応じて、ドキュメントにバッジが表示されるなどの特典がある場合があります。🎁
---

View File

@ -1,13 +1,12 @@
# 歴史、設計、そしてこれから
# 歴史、設計、そしてこれから { #history-design-and-future }
少し前に、<a href="https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920" class="external-link" target="_blank">**FastAPI**
のユーザーに以下の様に尋ねられました</a>:
少し前に、<a href="https://github.com/fastapi/fastapi/issues/3#issuecomment-454956920" class="external-link" target="_blank">**FastAPI**のユーザーに以下の様に尋ねられました</a>:
> このプロジェクトの歴史は?何もないところから、数週間ですごいものができているようです。 [...]
これがその歴史のほんの一部です。
## 代替手段
## 代替手段 { #alternatives }
数年前から、私は複雑な要件を持つAPI (機械学習、分散システム、非同期ジョブ、NoSQLデータベースなど) を作成しており、いくつかの開発者チームを率いています。
@ -19,7 +18,7 @@
<blockquote markdown="1">
**FastAPI**は、代替ツールのこれまでの働きがなければ存在しなかったでしょう。
**FastAPI**は、他の人々のこれまでの働きがなければ存在しなかったでしょう。
以前に作られた多くのツールが、作成における刺激として役立ってきました。
@ -29,7 +28,7 @@
</blockquote>
## 調査
## 調査 { #investigation }
すべて既存の代替手段を使うことで、そのすべてを学び、アイデアを得て、自分や一緒に仕事をしてきた開発者のチームにとって最良の方法で組み合わせる機会を得ました。
@ -39,7 +38,7 @@
そこで、**FastAPI**のコードを書き始める前に、OpenAPI、JSON Schema、OAuth2などの仕様を数ヶ月かけて勉強し、それらの関係、重複する箇所、相違点を理解しました。
## 設計
## 設計 { #design }
その後、 (FastAPIを使う開発者として) ユーザーが欲しい「API」の設計に時間を費やしました。
@ -53,19 +52,19 @@
すべての箇所で、すべての開発者に最高の開発体験を提供しました。
## 要件
## 要件 { #requirements }
いくつかの代替手法を試したあと、私は<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">**Pydantic**</a>の強みを利用することを決めました。
そして、JSON Schemaに完全に準拠するようにしたり、制約宣言を定義するさまざまな方法をサポートしたり、いくつかのエディターでのテストに基づいてエディターのサポート (型チェック、自動補完) を改善するために貢献しました。
開発中、もう1つの重要な鍵となる<a href="https://www.starlette.dev/" class="external-link" target="_blank">**Starlette**</a>にも貢献しました。
開発中、もう1つの重要な鍵となる<a href="https://www.starlette.dev/" class="external-link" target="_blank">**Starlette**</a>にも貢献しました。
## 開発
## 開発 { #development }
私が**FastAPI**自体の作成を開始した時には、ほとんどの部分がすでに準備されており、設計が定義され、必要な条件とツールの準備ができていました。そして規格や仕様に関する知識が、明確になり、更新されていました。
## これから
## これから { #future }
この時点ですでに、これらのアイデアを持った**FastAPI**が多くの人の役に立っていることは明らかです。

View File

@ -0,0 +1,17 @@
# 古い 403 認証エラーのステータスコードを使う { #use-old-403-authentication-error-status-codes }
FastAPI バージョン `0.122.0` より前は、統合されたセキュリティユーティリティが認証に失敗してクライアントへエラーを返す際、HTTP ステータスコード `403 Forbidden` を使用していました。
FastAPI バージョン `0.122.0` 以降では、より適切な HTTP ステータスコード `401 Unauthorized` を使用し、HTTP 仕様に従ってレスポンスに妥当な `WWW-Authenticate` ヘッダーを含めます。<a href="https://datatracker.ietf.org/doc/html/rfc7235#section-3.1" class="external-link" target="_blank">RFC 7235</a><a href="https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized" class="external-link" target="_blank">RFC 9110</a>
しかし、何らかの理由でクライアントが従来の挙動に依存している場合は、セキュリティクラスでメソッド `make_not_authenticated_error` をオーバーライドすることで、その挙動に戻せます。
たとえば、既定の `401 Unauthorized` エラーの代わりに `403 Forbidden` エラーを返す `HTTPBearer` のサブクラスを作成できます:
{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *}
/// tip | 豆知識
この関数は例外インスタンスを返す点に注意してください。ここでは例外を送出しません。送出は内部の他のコードで行われます。
///

View File

@ -10,7 +10,7 @@
もしセキュリティ上の欠陥がソースコードにあるならば、それは存在したままです。
ドキュメンテーションを非表示にするのは、単にあなたのAPIへのアクセス方法を難解にするだけでなく、同時にあなた自身の本番環境でのAPIのデバッグを困難にしてしまう可能性があります。単純に、 <a href="https://en.wikipedia.org/wiki/Security_through_obscurity" class="external-link" target="_blank">Security through obscurity</a> の一つの形態として考えられるでしょう。
ドキュメンテーションを非表示にするのは、単にあなたのAPIへのアクセス方法を難解にするだけでなく、同時にあなた自身の本番環境でのAPIのデバッグを困難にしてしまう可能性があります。単純に、 <a href="https://en.wikipedia.org/wiki/Security_through_obscurity" class="external-link" target="_blank">秘匿によるセキュリティ</a> の一つの形態として考えられるでしょう。
もしあなたのAPIのセキュリティを強化したいなら、いくつかのよりよい方法があります。例を示すと、
@ -29,7 +29,7 @@
例えば、
{* ../../docs_src/conditional_openapi/tutorial001_py39.py hl[6,11] *}
{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *}
ここでは `openapi_url` の設定を、デフォルトの `"/openapi.json"` のまま宣言しています。

View File

@ -0,0 +1,70 @@
# Swagger UI の設定 { #configure-swagger-ui }
いくつかの追加の <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/" class="external-link" target="_blank">Swagger UI パラメータ</a>を設定できます。
設定するには、`FastAPI()` のアプリオブジェクトを作成するとき、または `get_swagger_ui_html()` 関数に `swagger_ui_parameters` 引数を渡します。
`swagger_ui_parameters` は、Swagger UI に直接渡される設定を含む辞書を受け取ります。
FastAPI はそれらの設定を **JSON** に変換し、JavaScript と互換にします。Swagger UI が必要とするのはこの形式です。
## シンタックスハイライトを無効化 { #disable-syntax-highlighting }
例えば、Swagger UI のシンタックスハイライトを無効化できます。
設定を変更しなければ、シンタックスハイライトはデフォルトで有効です:
<img src="/img/tutorial/extending-openapi/image02.png">
しかし、`syntaxHighlight` を `False` に設定すると無効化できます:
{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *}
...その場合、Swagger UI ではシンタックスハイライトが表示されなくなります:
<img src="/img/tutorial/extending-openapi/image03.png">
## テーマの変更 { #change-the-theme }
同様に、キー `"syntaxHighlight.theme"`(途中にドットが含まれている点に注意)でシンタックスハイライトのテーマを設定できます:
{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *}
この設定により、シンタックスハイライトの配色テーマが変わります:
<img src="/img/tutorial/extending-openapi/image04.png">
## 既定の Swagger UI パラメータの変更 { #change-default-swagger-ui-parameters }
FastAPI には、多くのユースケースに適した既定の設定パラメータが含まれています。
既定では次の設定が含まれます:
{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *}
引数 `swagger_ui_parameters` に別の値を指定することで、これらを上書きできます。
例えば、`deepLinking` を無効化するには、次の設定を `swagger_ui_parameters` に渡します:
{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *}
## その他の Swagger UI パラメータ { #other-swagger-ui-parameters }
利用可能な他のすべての設定については、公式の <a href="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/" class="external-link" target="_blank">Swagger UI パラメータのドキュメント</a>を参照してください。
## JavaScript 専用の設定 { #javascript-only-settings }
Swagger UI では、他にも **JavaScript 専用** のオブジェクト(例: JavaScript の関数)による設定が可能です。
FastAPI には、次の JavaScript 専用の `presets` 設定も含まれています:
```JavaScript
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
]
```
これらは文字列ではなく **JavaScript** のオブジェクトであるため、Python のコードから直接渡すことはできません。
そのような JavaScript 専用の設定を使う必要がある場合は、上記のいずれかの方法を使用し、Swagger UI の path operation をオーバーライドして、必要な JavaScript を手動で記述してください。

View File

@ -0,0 +1,185 @@
# カスタムドキュメント UI の静的アセット(セルフホスティング) { #custom-docs-ui-static-assets-self-hosting }
API ドキュメントは **Swagger UI****ReDoc** を使用しており、それぞれにいくつかの JavaScript と CSS ファイルが必要です。
既定では、これらのファイルは <abbr title="Content Delivery Network - コンテンツ配信ネットワーク: 通常は複数のサーバーで構成され、JavaScript や CSS などの静的ファイルを提供するサービス。クライアントに近いサーバーからそれらのファイルを配信することで、パフォーマンスを改善するためによく使われます。">CDN</abbr> から配信されます。
しかし、カスタマイズすることも可能で、特定の CDN を指定したり、自分でファイルを配信したりできます。
## JavaScript と CSS のカスタム CDN { #custom-cdn-for-javascript-and-css }
別の <abbr title="Content Delivery Network - コンテンツ配信ネットワーク">CDN</abbr> を使いたいとします。例えば `https://unpkg.com/` を使いたい場合です。
例えば、一部の URL が制限されている国に住んでいる場合に役立ちます。
### 自動ドキュメントの無効化 { #disable-the-automatic-docs }
最初の手順は自動ドキュメントを無効化することです。デフォルトではそれらは既定の CDN を使用します。
無効化するには、`FastAPI` アプリ作成時にそれらの URL を `None` に設定します:
{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *}
### カスタムドキュメントの追加 { #include-the-custom-docs }
これで、カスタムドキュメント用の *path operations* を作成できます。
FastAPI の内部関数を再利用してドキュメント用の HTML ページを生成し、必要な引数を渡せます:
- `openapi_url`: ドキュメントの HTML ページが API の OpenAPI スキーマを取得する URL。ここでは属性 `app.openapi_url` を使用できます。
- `title`: API のタイトル。
- `oauth2_redirect_url`: 既定値を使うにはここで `app.swagger_ui_oauth2_redirect_url` を使用できます。
- `swagger_js_url`: Swagger UI ドキュメント用の HTML が取得する JavaScript ファイルの URL。これはカスタム CDN の URL です。
- `swagger_css_url`: Swagger UI ドキュメント用の HTML が取得する CSS ファイルの URL。これはカスタム CDN の URL です。
ReDoc についても同様です...
{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *}
/// tip | 豆知識
`swagger_ui_redirect` 用の *path operation* は、OAuth2 を使用する場合の補助です。
API を OAuth2 プロバイダと統合すると、認証を実行して取得したクレデンシャルを持った状態で API ドキュメントに戻れます。そして実際の OAuth2 認証を用いてドキュメント上から API と対話できます。
Swagger UI がこの処理を裏側で行いますが、そのためにこの「redirect」の補助が必要です。
///
### テスト用の *path operation* を作成 { #create-a-path-operation-to-test-it }
すべてが動作するかをテストできるように、*path operation* を作成します:
{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *}
### テスト { #test-it }
これで、<a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> にアクセスしてページを再読み込みすると、新しい CDN からそれらのアセットが読み込まれるはずです。
## ドキュメント用 JavaScript と CSS のセルフホスティング { #self-hosting-javascript-and-css-for-docs }
オフラインインターネット非接続でも、あるいはローカルネットワークで、アプリを動作させたい場合などには、JavaScript と CSS をセルフホストするのが有用です。
ここでは、同じ FastAPI アプリ内でそれらのファイルを配信し、ドキュメントでそれらを使用するように設定する方法を示します。
### プロジェクトのファイル構成 { #project-file-structure }
プロジェクトのファイル構成が次のようになっているとします:
```
.
├── app
│ ├── __init__.py
│ ├── main.py
```
これらの静的ファイルを保存するためのディレクトリを作成します。
新しいファイル構成は次のようになります:
```
.
├── app
│   ├── __init__.py
│   ├── main.py
└── static/
```
### ファイルのダウンロード { #download-the-files }
ドキュメントに必要な静的ファイルをダウンロードし、`static/` ディレクトリに配置します。
各リンクを右クリックして「リンク先を別名で保存...」のようなオプションを選べます。
**Swagger UI** では次のファイルを使用します:
- <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js" class="external-link" target="_blank">`swagger-ui-bundle.js`</a>
- <a href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css" class="external-link" target="_blank">`swagger-ui.css`</a>
そして **ReDoc** では次のファイルを使用します:
- <a href="https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js" class="external-link" target="_blank">`redoc.standalone.js`</a>
その後、ファイル構成は次のようになります:
```
.
├── app
│   ├── __init__.py
│   ├── main.py
└── static
├── redoc.standalone.js
├── swagger-ui-bundle.js
└── swagger-ui.css
```
### 静的ファイルの配信 { #serve-the-static-files }
- `StaticFiles` をインポートします。
- 特定のパスに `StaticFiles()` インスタンスを「マウント」します。
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *}
### 静的ファイルのテスト { #test-the-static-files }
アプリケーションを起動し、<a href="http://127.0.0.1:8000/static/redoc.standalone.js" class="external-link" target="_blank">http://127.0.0.1:8000/static/redoc.standalone.js</a> にアクセスします。
**ReDoc** 用の非常に長い JavaScript ファイルが表示されるはずです。
先頭は次のようになっているかもしれません:
```JavaScript
/*! For license information please see redoc.standalone.js.LICENSE.txt */
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")):
...
```
これで、アプリから静的ファイルを配信できていること、そしてドキュメント用の静的ファイルを正しい場所に配置できていることが確認できます。
次に、ドキュメントでそれらの静的ファイルを使用するようにアプリを設定します。
### 静的ファイル用に自動ドキュメントを無効化 { #disable-the-automatic-docs-for-static-files }
カスタム CDN を使う場合と同様、最初の手順は自動ドキュメントを無効化することです。既定では CDN を使用します。
無効化するには、`FastAPI` アプリ作成時にそれらの URL を `None` に設定します:
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *}
### 静的ファイル用のカスタムドキュメントを追加 { #include-the-custom-docs-for-static-files }
カスタム CDN と同様の方法で、カスタムドキュメント用の *path operations* を作成できます。
再び、FastAPI の内部関数を再利用してドキュメント用の HTML ページを生成し、必要な引数を渡します:
- `openapi_url`: ドキュメントの HTML ページが API の OpenAPI スキーマを取得する URL。ここでは属性 `app.openapi_url` を使用できます。
- `title`: API のタイトル。
- `oauth2_redirect_url`: 既定値を使うにはここで `app.swagger_ui_oauth2_redirect_url` を使用できます。
- `swagger_js_url`: Swagger UI ドキュメント用の HTML が取得する **JavaScript** ファイルの URL。**これはあなたのアプリ自身がいま配信しているものです**。
- `swagger_css_url`: Swagger UI ドキュメント用の HTML が取得する **CSS** ファイルの URL。**これはあなたのアプリ自身がいま配信しているものです**。
ReDoc についても同様です...
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *}
/// tip | 豆知識
`swagger_ui_redirect` 用の *path operation* は、OAuth2 を使用する場合の補助です。
API を OAuth2 プロバイダと統合すると、認証を実行して取得したクレデンシャルを持った状態で API ドキュメントに戻れます。そして実際の OAuth2 認証を用いてドキュメント上から API と対話できます。
Swagger UI がこの処理を裏側で行いますが、そのためにこの「redirect」の補助が必要です。
///
### 静的ファイルをテストするための *path operation* を作成 { #create-a-path-operation-to-test-static-files }
すべてが動作するかをテストできるように、*path operation* を作成します:
{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *}
### 静的ファイル UI のテスト { #test-static-files-ui }
これで、WiFi を切断して <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> にアクセスし、ページを再読み込みできるはずです。
インターネットに接続していなくても、API のドキュメントを表示し、API と対話できます。

View File

@ -0,0 +1,109 @@
# カスタム Request と APIRoute クラス { #custom-request-and-apiroute-class }
場合によっては、`Request` や `APIRoute` クラスで使われるロジックを上書きしたいことがあります。
特に、ミドルウェアでのロジックの代替として有効な場合があります。
たとえば、アプリケーションで処理される前にリクエストボディを読み取ったり操作したりしたい場合です。
/// danger | 警告
これは「上級」機能です。
FastAPI を始めたばかりの場合は、このセクションは読み飛ばしてもよいでしょう。
///
## ユースケース { #use-cases }
ユースケースの例:
* JSON ではないリクエストボディを JSON に変換する(例: <a href="https://msgpack.org/index.html" class="external-link" target="_blank">`msgpack`</a>)。
* gzip 圧縮されたリクエストボディの解凍。
* すべてのリクエストボディの自動ロギング。
## カスタムリクエストボディのエンコーディングの処理 { #handling-custom-request-body-encodings }
gzip のリクエストを解凍するために、カスタムの `Request` サブクラスを使う方法を見ていきます。
そして、そのカスタムリクエストクラスを使うための `APIRoute` サブクラスを用意します。
### カスタム `GzipRequest` クラスの作成 { #create-a-custom-gziprequest-class }
/// tip | 豆知識
これは仕組みを示すためのサンプルです。Gzip 対応が必要な場合は、用意されている [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware){.internal-link target=_blank} を使用できます。
///
まず、`GzipRequest` クラスを作成します。これは適切なヘッダーがある場合に本体を解凍するよう、`Request.body()` メソッドを上書きします。
ヘッダーに `gzip` がなければ、解凍は試みません。
この方法により、同じルートクラスで gzip 圧縮済み/未圧縮のリクエストの両方を扱えます。
{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *}
### カスタム `GzipRoute` クラスの作成 { #create-a-custom-gziproute-class }
次に、`GzipRequest` を利用する `fastapi.routing.APIRoute` のカスタムサブクラスを作成します。
ここでは `APIRoute.get_route_handler()` メソッドを上書きします。
このメソッドは関数を返します。そしてその関数がリクエストを受け取り、レスポンスを返します。
ここでは、元のリクエストから `GzipRequest` を作成するために利用します。
{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *}
/// note | 技術詳細
`Request` には `request.scope` 属性があり、これはリクエストに関するメタデータを含む Python の `dict` です。
`Request` には `request.receive` もあり、これはリクエストの本体を「受信」するための関数です。
`scope``dict``receive` 関数はいずれも ASGI 仕様の一部です。
そしてこの 2 つ(`scope` と `receive`)が、新しい `Request` インスタンスを作成するために必要なものです。
`Request` について詳しくは、<a href="https://www.starlette.dev/requests/" class="external-link" target="_blank">Starlette の Requests に関するドキュメント</a> を参照してください。
///
`GzipRequest.get_route_handler` が返す関数が異なるのは、`Request` を `GzipRequest` に変換する点だけです。
これにより、`GzipRequest` は必要に応じてデータを解凍してから *path operations* に渡します。
それ以降の処理ロジックはすべて同じです。
ただし、`GzipRequest.body` を変更しているため、必要に応じて **FastAPI** によって読み込まれる際にリクエストボディが自動的に解凍されます。
## 例外ハンドラでのリクエストボディへのアクセス { #accessing-the-request-body-in-an-exception-handler }
/// tip | 豆知識
同じ問題を解決するには、`RequestValidationError` 用のカスタムハンドラで `body` を使う方がずっと簡単でしょう([エラー処理](../tutorial/handling-errors.md#use-the-requestvalidationerror-body){.internal-link target=_blank})。
ただし、この例も有効で、内部コンポーネントとどのようにやり取りするかを示しています。
///
同じアプローチを使って、例外ハンドラ内でリクエストボディにアクセスすることもできます。
やることは、`try`/`except` ブロックの中でリクエストを処理するだけです:
{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *}
例外が発生しても、`Request` インスタンスはスコープ内に残るため、エラー処理時にリクエストボディを読み取り、活用できます:
{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *}
## ルーターでのカスタム `APIRoute` クラス { #custom-apiroute-class-in-a-router }
`APIRouter``route_class` パラメータを設定することもできます:
{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *}
この例では、`router` 配下の *path operations* はカスタムの `TimedRoute` クラスを使用し、レスポンスの生成にかかった時間を示す追加の `X-Response-Time` ヘッダーがレスポンスに含まれます:
{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *}

View File

@ -0,0 +1,80 @@
# OpenAPI の拡張 { #extending-openapi }
生成された OpenAPI スキーマを変更する必要がある場合があります。
このセクションではその方法を説明します。
## 通常のプロセス { #the-normal-process }
通常(デフォルト)のプロセスは次のとおりです。
`FastAPI` アプリケーションインスタンスには、OpenAPI スキーマを返すことが期待される `.openapi()` メソッドがあります。
アプリケーションオブジェクトの作成時に、`/openapi.json`(または `openapi_url` に設定したパス)への path operation が登録されます。
これは単に、アプリケーションの `.openapi()` メソッドの結果を含む JSON レスポンスを返します。
デフォルトでは、`.openapi()` メソッドはプロパティ `.openapi_schema` に内容があるかを確認し、あればそれを返します。
なければ、`fastapi.openapi.utils.get_openapi` にあるユーティリティ関数を使って生成します。
この関数 `get_openapi()` は次の引数を受け取ります:
- `title`: ドキュメントに表示される OpenAPI のタイトル。
- `version`: API のバージョン。例: `2.5.0`
- `openapi_version`: 使用する OpenAPI 仕様のバージョン。デフォルトは最新の `3.1.0`
- `summary`: API の短い概要。
- `description`: API の説明。Markdown を含めることができ、ドキュメントに表示されます。
- `routes`: ルートのリスト。登録済みの各 path operation です。`app.routes` から取得されます。
/// info | 情報
パラメータ `summary` は OpenAPI 3.1.0 以降で利用可能で、FastAPI 0.99.0 以降が対応しています。
///
## デフォルトの上書き { #overriding-the-defaults }
上記の情報を使って、同じユーティリティ関数で OpenAPI スキーマを生成し、必要な部分を上書きできます。
たとえば、<a href="https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo" class="external-link" target="_blank">カスタムロゴを含めるための ReDoc の OpenAPI 拡張</a>を追加してみましょう。
### 通常の **FastAPI** { #normal-fastapi }
まず、通常どおりに **FastAPI** アプリケーションを実装します:
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *}
### OpenAPI スキーマの生成 { #generate-the-openapi-schema }
次に、`custom_openapi()` 関数内で同じユーティリティ関数を使って OpenAPI スキーマを生成します:
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *}
### OpenAPI スキーマの変更 { #modify-the-openapi-schema }
OpenAPI スキーマの `info`「オブジェクト」にカスタムの `x-logo` を追加して、ReDoc 拡張を加えます:
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *}
### OpenAPI スキーマのキャッシュ { #cache-the-openapi-schema }
生成したスキーマを保持する「キャッシュ」として `.openapi_schema` プロパティを利用できます。
こうすることで、ユーザーが API ドキュメントを開くたびにスキーマを生成する必要がなくなります。
最初の1回だけ生成され、その後は同じキャッシュ済みスキーマが以降のリクエストで使われます。
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *}
### メソッドの上書き { #override-the-method }
これで、`.openapi()` メソッドを新しい関数に置き換えられます。
{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *}
### 確認 { #check-it }
<a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> にアクセスすると、カスタムロゴ(この例では **FastAPI** のロゴ)が使われていることが確認できます:
<img src="/img/tutorial/extending-openapi/image01.png">

View File

@ -0,0 +1,39 @@
# 一般 - ハウツー - レシピ { #general-how-to-recipes }
ここでは、一般的またはよくある質問に対して、ドキュメント内の他の箇所への参照をいくつか示します。
## データのフィルタリング - セキュリティ { #filter-data-security }
返すべき以上のデータを返さないようにするには、[チュートリアル - レスポンスモデル - 戻り値の型](../tutorial/response-model.md){.internal-link target=_blank} を参照してください。
## ドキュメントのタグ - OpenAPI { #documentation-tags-openapi }
*path operations* にタグを追加し、ドキュメント UI でグループ化するには、[チュートリアル - path operation の設定 - タグ](../tutorial/path-operation-configuration.md#tags){.internal-link target=_blank} を参照してください。
## ドキュメントの概要と説明 - OpenAPI { #documentation-summary-and-description-openapi }
*path operations* に概要と説明を追加し、ドキュメント UI に表示するには、[チュートリアル - path operation の設定 - 概要と説明](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} を参照してください。
## ドキュメントのレスポンス説明 - OpenAPI { #documentation-response-description-openapi }
ドキュメント UI に表示されるレスポンスの説明を定義するには、[チュートリアル - path operation の設定 - レスポンスの説明](../tutorial/path-operation-configuration.md#response-description){.internal-link target=_blank} を参照してください。
## *Path Operation* の非推奨化 - OpenAPI { #documentation-deprecate-a-path-operation-openapi }
*path operation* を非推奨にし、ドキュメント UI に表示するには、[チュートリアル - path operation の設定 - 非推奨](../tutorial/path-operation-configuration.md#deprecate-a-path-operation){.internal-link target=_blank} を参照してください。
## 任意のデータを JSON 互換に変換 { #convert-any-data-to-json-compatible }
任意のデータを JSON 互換に変換するには、[チュートリアル - JSON 互換エンコーダ](../tutorial/encoder.md){.internal-link target=_blank} を参照してください。
## OpenAPI メタデータ - ドキュメント { #openapi-metadata-docs }
ライセンス、バージョン、連絡先などを含むメタデータを OpenAPI スキーマに追加するには、[チュートリアル - メタデータとドキュメントの URL](../tutorial/metadata.md){.internal-link target=_blank} を参照してください。
## OpenAPI のカスタム URL { #openapi-custom-url }
OpenAPI の URL をカスタマイズ(または削除)するには、[チュートリアル - メタデータとドキュメントの URL](../tutorial/metadata.md#openapi-url){.internal-link target=_blank} を参照してください。
## OpenAPI ドキュメントの URL { #openapi-docs-urls }
自動生成されるドキュメント UI が使用する URL を変更するには、[チュートリアル - メタデータとドキュメントの URL](../tutorial/metadata.md#docs-urls){.internal-link target=_blank} を参照してください。

View File

@ -0,0 +1,60 @@
# GraphQL { #graphql }
**FastAPI** は **ASGI** 標準に基づいているため、ASGI に対応した任意の **GraphQL** ライブラリを簡単に統合できます。
同じアプリケーション内で通常の FastAPI の *path operation* と GraphQL を組み合わせて使えます。
/// tip | 豆知識
**GraphQL** は非常に特定のユースケースを解決します。
一般的な **Web API** と比べると、**長所** と **短所** があります。
ご自身のユースケースで得られる **利点****欠点** を補うかどうかを評価してください。 🤓
///
## GraphQL ライブラリ { #graphql-libraries }
**ASGI** をサポートする **GraphQL** ライブラリの一部を以下に示します。**FastAPI** と組み合わせて使用できます:
* <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry</a> 🍓
* <a href="https://strawberry.rocks/docs/integrations/fastapi" class="external-link" target="_blank">FastAPI 向けドキュメント</a>あり
* <a href="https://ariadnegraphql.org/" class="external-link" target="_blank">Ariadne</a>
* <a href="https://ariadnegraphql.org/docs/fastapi-integration" class="external-link" target="_blank">FastAPI 向けドキュメント</a>あり
* <a href="https://tartiflette.io/" class="external-link" target="_blank">Tartiflette</a>
* ASGI 連携用の <a href="https://tartiflette.github.io/tartiflette-asgi/" class="external-link" target="_blank">Tartiflette ASGI</a> あり
* <a href="https://graphene-python.org/" class="external-link" target="_blank">Graphene</a>
* <a href="https://github.com/ciscorn/starlette-graphene3" class="external-link" target="_blank">starlette-graphene3</a> あり
## Strawberry で GraphQL { #graphql-with-strawberry }
**GraphQL** が必要、または利用したい場合は、<a href="https://strawberry.rocks/" class="external-link" target="_blank">**Strawberry**</a> を**推奨**します。**FastAPI** の設計に最も近く、すべてが**型アノテーション**に基づいています。
ユースケースによっては他のライブラリを選ぶ方がよい場合もありますが、私に尋ねられれば、おそらく **Strawberry** を試すことを勧めるでしょう。
FastAPI と Strawberry を統合する方法の簡単なプレビューです:
{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *}
詳細は <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry のドキュメント</a>をご覧ください。
また、<a href="https://strawberry.rocks/docs/integrations/fastapi" class="external-link" target="_blank">Strawberry と FastAPI</a> の連携に関するドキュメントもあります。
## Starlette の旧 `GraphQLApp` { #older-graphqlapp-from-starlette }
以前の Starlette には、<a href="https://graphene-python.org/" class="external-link" target="_blank">Graphene</a> と統合するための `GraphQLApp` クラスが含まれていました。
これは Starlette からは非推奨になりましたが、もしそれを使用しているコードがある場合は、同じユースケースをカバーし、**ほぼ同一のインターフェース**を持つ <a href="https://github.com/ciscorn/starlette-graphene3" class="external-link" target="_blank">starlette-graphene3</a> へ容易に**移行**できます。
/// tip | 豆知識
GraphQL が必要であれば、依然として <a href="https://strawberry.rocks/" class="external-link" target="_blank">Strawberry</a> の利用を推奨します。独自のクラスや型ではなく、型アノテーションに基づいているためです。
///
## さらに学ぶ { #learn-more }
**GraphQL** については、<a href="https://graphql.org/" class="external-link" target="_blank">公式 GraphQL ドキュメント</a>でさらに学べます。
上記の各ライブラリについては、リンク先のドキュメントをご参照ください。

View File

@ -0,0 +1,13 @@
# ハウツー - レシピ { #how-to-recipes }
ここでは、**複数のトピック**に関するさまざまなレシピや「ハウツー」ガイドを紹介します。
これらのアイデアの多くはおおむね**独立**しており、ほとんどの場合、**あなたのプロジェクト**に直接当てはまるものだけを読めば十分です。
プロジェクトにとって興味深く有用だと思うものがあれば、ぜひ確認してください。そうでなければ、読み飛ばしても問題ありません。
/// tip | 豆知識
**FastAPI を学ぶ**ことを体系的に進めたい場合(推奨)、代わりに [チュートリアル - ユーザーガイド](../tutorial/index.md){.internal-link target=_blank} を章ごとに読んでください。
///

View File

@ -0,0 +1,135 @@
# Pydantic v1 から Pydantic v2 への移行 { #migrate-from-pydantic-v1-to-pydantic-v2 }
古い FastAPI アプリがある場合、Pydantic v1 を使っているかもしれません。
FastAPI 0.100.0 は Pydantic v1 / v2 のどちらにも対応しており、インストールされている方を使用しました。
FastAPI 0.119.0 では、Pydantic v2 内からの Pydantic v1 の部分的サポート(`pydantic.v1`が導入され、v2 への移行が容易になりました。
FastAPI 0.126.0 で Pydantic v1 のサポートは終了しましたが、しばらくの間は `pydantic.v1` は利用可能でした。
/// warning | 注意
Pydantic チームは Python の最新バージョン、つまり **Python 3.14** から、Pydantic v1 のサポートを終了しました。
これには `pydantic.v1` も含まれ、Python 3.14 以上ではサポートされません。
Python の最新機能を使いたい場合は、Pydantic v2 を使用していることを確認する必要があります。
///
古い FastAPI アプリで Pydantic v1 を使っている場合、ここでは Pydantic v2 への移行方法と、段階的移行を助ける **FastAPI 0.119.0 の機能** を紹介します。
## 公式ガイド { #official-guide }
Pydantic には v1 から v2 への公式の <a href="https://docs.pydantic.dev/latest/migration/" class="external-link" target="_blank">移行ガイド</a> があります。
変更点、検証がより正確で厳密になった点、注意事項などが含まれます。
何が変わったかをよりよく理解するために参照してください。
## テスト { #tests }
アプリに対する[テスト](../tutorial/testing.md){.internal-link target=_blank}を用意し、継続的インテグレーションCIで実行するようにしてください。
これにより、アップグレード後も期待どおり動作していることを確認できます。
## `bump-pydantic` { #bump-pydantic }
多くの場合、カスタマイズのない通常の Pydantic モデルを使っていれば、v1 から v2 への移行作業の大半を自動化できます。
同じ Pydantic チームが提供する <a href="https://github.com/pydantic/bump-pydantic" class="external-link" target="_blank">`bump-pydantic`</a> を使用できます。
このツールは必要なコード変更のほとんどを自動で行います。
その後テストを実行し、問題なければ完了です。😎
## v2 における Pydantic v1 { #pydantic-v1-in-v2 }
Pydantic v2 には、Pydantic v1 がサブモジュール `pydantic.v1` として同梱されています。ただし、これは Python 3.13 を超えるバージョンではサポートされません。
つまり、Pydantic v2 の最新バージョンをインストールし、このサブモジュールから旧 Pydantic v1 のコンポーネントをインポートして、あたかも v1 をインストールしているかのように使用できます。
{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *}
### v2 内の Pydantic v1 に対する FastAPI のサポート { #fastapi-support-for-pydantic-v1-in-v2 }
FastAPI 0.119.0 以降では、移行を容易にするため、Pydantic v2 内の Pydantic v1 に対する部分的サポートもあります。
そのため、Pydantic を v2 の最新に上げ、インポートを `pydantic.v1` サブモジュールに切り替えるだけで、多くの場合そのまま動作します。
{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *}
/// warning | 注意
前述のとおり、Python の最近のバージョンPython 3.14 以降)では Pydantic v1 がサポートされないため、`pydantic.v1` の使用も Python 3.14 以上ではサポートされません。
///
### 同一アプリでの Pydantic v1 と v2 { #pydantic-v1-and-v2-on-the-same-app }
Pydantic v2 のモデルのフィールドに Pydantic v1 のモデルをまたはその逆を埋め込むことは、Pydantic では「サポートされていません」。
```mermaid
graph TB
subgraph "❌ Not Supported"
direction TB
subgraph V2["Pydantic v2 Model"]
V1Field["Pydantic v1 Model"]
end
subgraph V1["Pydantic v1 Model"]
V2Field["Pydantic v2 Model"]
end
end
style V2 fill:#f9fff3
style V1 fill:#fff6f0
style V1Field fill:#fff6f0
style V2Field fill:#f9fff3
```
...but, you can have separated models using Pydantic v1 and v2 in the same app.
```mermaid
graph TB
subgraph "✅ Supported"
direction TB
subgraph V2["Pydantic v2 Model"]
V2Field["Pydantic v2 Model"]
end
subgraph V1["Pydantic v1 Model"]
V1Field["Pydantic v1 Model"]
end
end
style V2 fill:#f9fff3
style V1 fill:#fff6f0
style V1Field fill:#fff6f0
style V2Field fill:#f9fff3
```
場合によっては、同じ FastAPI の path operation 内で、Pydantic v1 と v2 の両方のモデルを扱うことも可能です:
{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *}
上の例では、入力モデルは Pydantic v1、出力モデル`response_model=ItemV2` で定義)は Pydantic v2 です。
### Pydantic v1 のパラメータ { #pydantic-v1-parameters }
Pydantic v1 のモデルで `Body`、`Query`、`Form` などの FastAPI 固有のパラメータユーティリティを使う必要がある場合、v2 への移行が完了するまでの間は `fastapi.temp_pydantic_v1_params` からインポートできます:
{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *}
### 段階的に移行 { #migrate-in-steps }
/// tip | 豆知識
まずは `bump-pydantic` を試してください。テストが通り、問題なければコマンド一発で完了です。✨
///
`bump-pydantic` が適用できない場合は、同一アプリで v1 と v2 のモデルを併用できるサポートを利用して、徐々に v2 へ移行できます。
まず Pydantic を v2 の最新にアップグレードし、すべてのモデルのインポートを `pydantic.v1` に切り替えます。
その後、モデルをグループごとに少しずつ Pydantic v1 から v2 へ移行していきます。🚶

View File

@ -0,0 +1,102 @@
# 入力と出力でOpenAPIのスキーマを分けるかどうか { #separate-openapi-schemas-for-input-and-output-or-not }
**Pydantic v2** のリリース以降、生成される OpenAPI は以前より少し正確で、より正しいものになりました。😎
実際には、場合によっては同じ Pydantic モデルに対して、入力用と出力用で OpenAPI に **2 つの JSON Schema** が含まれることがあります。これは **デフォルト値** の有無に依存します。
その動作と、必要に応じての変更方法を見ていきます。
## 入出力のPydanticモデル { #pydantic-models-for-input-and-output }
次のようにデフォルト値を持つ Pydantic モデルがあるとします。
{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *}
### 入力用モデル { #model-for-input }
このモデルを次のように入力として使うと:
{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *}
...`description` フィールドは **必須ではありません**。デフォルト値が `None` だからです。
### ドキュメントでの入力モデル { #input-model-in-docs }
ドキュメントで確認すると、`description` フィールドには **赤いアスタリスク** が付いておらず、必須としてはマークされていません:
<div class="screenshot">
<img src="/img/tutorial/separate-openapi-schemas/image01.png">
</div>
### 出力用モデル { #model-for-output }
しかし同じモデルを次のように出力として使う場合:
{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *}
...`description` にデフォルト値があるため、そのフィールドに何も返さなくても、その **デフォルト値** が入ります。
### 出力のレスポンスデータ { #model-for-output-response-data }
ドキュメントから試してレスポンスを確認すると、コードでは一方の `description` フィールドに何も追加していないにもかかわらず、JSON レスポンスにはデフォルト値(`null`)が含まれています:
<div class="screenshot">
<img src="/img/tutorial/separate-openapi-schemas/image02.png">
</div>
つまりそのフィールドには **常に値があります**。値が `None`JSON では `null`)になることがあるだけです。
したがって、この API を使うクライアントは値の有無を確認する必要がなく、フィールドが **常に存在する** と仮定できます。場合によってはデフォルト値の `None` になるだけです。
これを OpenAPI で表現するには、そのフィールドを **必須** としてマークします。常に存在するためです。
このため、モデルの JSON Schema は、**入力か出力か** によって異なる場合があります:
- **入力** では `description` は **必須ではない**
- **出力** では **必須**(値は `None`、JSON では `null` の可能性あり)
### ドキュメントでの出力モデル { #model-for-output-in-docs }
ドキュメントで出力モデルを見ると、`name` と `description`**両方****赤いアスタリスク****必須** としてマークされています:
<div class="screenshot">
<img src="/img/tutorial/separate-openapi-schemas/image03.png">
</div>
### ドキュメントでの入力・出力モデル { #model-for-input-and-output-in-docs }
さらに、OpenAPI に含まれる利用可能なスキーマJSON Schemaを確認すると、`Item-Input` と `Item-Output` の 2 つがあることが分かります。
`Item-Input` では、`description` は **必須ではありません**(赤いアスタリスクなし)。
一方、`Item-Output` では、`description` は **必須**(赤いアスタリスクあり)です。
<div class="screenshot">
<img src="/img/tutorial/separate-openapi-schemas/image04.png">
</div>
この **Pydantic v2** の機能により、API ドキュメントはより **正確** になり、自動生成されたクライアントや SDK もより正確になります。これにより、より良い **開発者エクスペリエンス** と一貫性が得られます。🎉
## スキーマを分けない { #do-not-separate-schemas }
一方で、**入力と出力で同じスキーマ** にしたい場合もあります。
主なユースケースは、すでに自動生成されたクライアントコードや SDK があり、まだそれらをすべて更新したくない場合です。いずれは更新したいとしても、今ではないかもしれません。
その場合は、**FastAPI** のパラメータ `separate_input_output_schemas=False` でこの機能を無効化できます。
/// info | 情報
`separate_input_output_schemas` のサポートは FastAPI `0.102.0` で追加されました。🤓
///
{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *}
### ドキュメントで入力・出力に同一スキーマを使用 { #same-schema-for-input-and-output-models-in-docs }
これでモデルの入力と出力は単一のスキーマ、`Item` のみになり、`description` は **必須ではありません**:
<div class="screenshot">
<img src="/img/tutorial/separate-openapi-schemas/image05.png">
</div>

View File

@ -0,0 +1,7 @@
# データベースのテスト { #testing-a-database }
データベース、SQL、SQLModel については、<a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_blank">SQLModel ドキュメント</a>で学べます。🤓
FastAPI と一緒に SQLModel を使うためのミニ <a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/" class="external-link" target="_blank">チュートリアル</a>があります。✨
そのチュートリアルには、<a href="https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/" class="external-link" target="_blank">SQL データベースのテスト</a>に関するセクションも含まれています。😎

View File

@ -40,7 +40,7 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP
* **高速**: **NodeJS****Go** 並みのとても高いパフォーマンスStarlette と Pydantic のおかげです)。 [利用可能な最も高速な Python フレームワークの一つです](#performance)。
* **高速なコーディング**: 開発速度を約 200%〜300% 向上させます。*
* **少ないバグ**: 開発者起因のヒューマンエラーを約 40% 削減します。*
* **直感的**: 素晴らしいエディタサポート。あらゆる場所で <abbr title="also known as auto-complete, autocompletion, IntelliSense">補完</abbr>使えます。デバッグ時間を削減します。
* **直感的**: 素晴らしいエディタサポート。<dfn title="別名: auto-complete、autocompletion、IntelliSense">補完</dfn> があらゆる場所で使えます。デバッグ時間を削減します。
* **簡単**: 簡単に利用・習得できるようにデザインされています。ドキュメントを読む時間を削減します。
* **短い**: コードの重複を最小限にします。各パラメータ宣言から複数の機能を得られます。バグも減ります。
* **堅牢性**: 自動対話型ドキュメントにより、本番環境向けのコードが得られます。
@ -127,7 +127,7 @@ FastAPI は、Python の標準である型ヒントに基づいて Python で AP
<a href="https://typer.tiangolo.com" target="_blank"><img src="https://typer.tiangolo.com/img/logo-margin/logo-margin-vector.svg" style="width: 20%;"></a>
Web API の代わりにターミナルで使用する <abbr title="Command Line Interface">CLI</abbr> アプリを構築する場合は、<a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a> を確認してください。
Web API の代わりにターミナルで使用する <abbr title="Command Line Interface - コマンドラインインターフェイス">CLI</abbr> アプリを構築する場合は、<a href="https://typer.tiangolo.com/" class="external-link" target="_blank">**Typer**</a> を確認してください。
**Typer** は FastAPI の弟分です。そして、**CLI 版 FastAPI** を意図しています。 ⌨️ 🚀
@ -368,7 +368,7 @@ item: Item
* データの検証:
* データが無効な場合に自動で明確なエラーを返します。
* 深い入れ子になった JSON オブジェクトでも検証が可能です。
* 入力データの <abbr title="also known as: serialization, parsing, marshalling">変換</abbr>: ネットワークから Python のデータや型へ。以下から読み取ります:
* 入力データの <dfn title="別名: serialization、parsing、marshalling">変換</dfn>: ネットワークから Python のデータや型へ。以下から読み取ります:
* JSON。
* パスパラメータ。
* クエリパラメータ。
@ -376,7 +376,7 @@ item: Item
* ヘッダー。
* フォーム。
* ファイル。
* 出力データの <abbr title="also known as: serialization, parsing, marshalling">変換</abbr>: Python のデータや型からネットワークデータへJSON として)変換します:
* 出力データの <dfn title="別名: serialization、parsing、marshalling">変換</dfn>: Python のデータや型からネットワークデータへJSON として)変換します:
* Python の型(`str`、`int`、`float`、`bool`、`list` など)の変換。
* `datetime` オブジェクト。
* `UUID` オブジェクト。
@ -439,7 +439,7 @@ item: Item
* **ヘッダー**、**Cookie**、**フォームフィールド**、**ファイル**など、他のさまざまな場所からの **パラメータ** 宣言。
* `maximum_length``regex` のような **検証制約** を設定する方法。
* 非常に強力で使いやすい **<abbr title="also known as components, resources, providers, services, injectables">依存性注入</abbr>** システム。
* 非常に強力で使いやすい **<dfn title="別名: components、resources、providers、services、injectables">依存性注入</dfn>** システム。
* **JWT トークン**を用いた **OAuth2****HTTP Basic** 認証のサポートを含む、セキュリティと認証。
* **深くネストされた JSON モデル**を宣言するための、より高度なしかし同様に簡単な手法Pydantic のおかげです)。
* <a href="https://strawberry.rocks" class="external-link" target="_blank">Strawberry</a> および他のライブラリによる **GraphQL** 統合。
@ -524,7 +524,7 @@ Starlette によって使用されるもの:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - `TestClient` を使用したい場合に必要です。
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - デフォルトのテンプレート設定を使用したい場合に必要です。
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - `request.form()` とともに、フォームの <abbr title="converting the string that comes from an HTTP request into Python data">「parsing」</abbr> をサポートしたい場合に必要です。
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - `request.form()` とともに、フォームの <dfn title="HTTP リクエストから届く文字列を Python データに変換すること">「parsing」</dfn> をサポートしたい場合に必要です。
FastAPI によって使用されるもの:

View File

@ -1,12 +1,12 @@
# Pythonの型の紹介 { #python-types-intro }
Pythonはオプションの「型ヒント」(「型アノテーション」とも呼ばれます)がサポートされています。
Pythonはオプションの「型ヒント」(「型アノテーション」とも呼ばれます)がサポートされています。
これらの **「型ヒント」** またはアノテーションは、変数の<abbr title="for example: str, int, float, bool"></abbr>を宣言できる特別な構文です。
これらの **「型ヒント」** やアノテーションは、変数の<dfn title="例えば: str、int、float、bool"></dfn>を宣言できる特別な構文です。
変数に型を宣言することで、エディターやツールがより良いサポートを提供できます。
これはPythonの型ヒントについての **クイックチュートリアル/リフレッシュ** にすぎません。**FastAPI** で使用するために必要な最低限のことだけをカバーしています。...実際には本当に少ないです。
これは Python の型ヒントについての **クイックチュートリアル/リフレッシュ** にすぎません。**FastAPI** で使ために必要な最低限のことだけをカバーしています。...実際には本当に少ないです。
**FastAPI** はすべてこれらの型ヒントに基づいており、多くの強みと利点を与えてくれます。
@ -14,7 +14,7 @@ Pythonではオプションの「型ヒント」「型アテーション
/// note | 備考
もしあなたがPythonの専門家で、すでに型ヒントについてすべて知っているのであれば、次の章まで読み飛ばしてください。
もしあなたが Python の専門家で、すでに型ヒントについてすべて知っているのであれば、次の章まで読み飛ばしてください。
///
@ -22,7 +22,7 @@ Pythonではオプションの「型ヒント」「型アテーション
簡単な例から始めてみましょう:
{* ../../docs_src/python_types/tutorial001_py39.py *}
{* ../../docs_src/python_types/tutorial001_py310.py *}
このプログラムを呼び出すと、以下が出力されます:
@ -32,11 +32,11 @@ John Doe
この関数は以下のようなことを行います:
* `first_name`と`last_name`を取得します。
* `title()`を用いて、それぞれの最初の文字を大文字に変換します。
* 真ん中にスペースを入れて<abbr title="Puts them together, as one. With the contents of one after the other.">連結</abbr>します。
* `first_name` `last_name` を取得します。
* `title()` を用いて、それぞれの最初の文字を大文字に変換します。
* 真ん中にスペースを入れて<dfn title="1つにまとめます。片方の内容をもう片方の後ろに続けます。">連結</dfn>します。
{* ../../docs_src/python_types/tutorial001_py39.py hl[2] *}
{* ../../docs_src/python_types/tutorial001_py310.py hl[2] *}
### 編集 { #edit-it }
@ -48,11 +48,11 @@ John Doe
しかし、そうすると「最初の文字を大文字に変換するあのメソッド」を呼び出す必要があります。
それは`upper`でしたか?`uppercase`でしたか?`first_uppercase``capitalize`
それは `upper` でしたか?`uppercase` でしたか?`first_uppercase``capitalize`
そして、古くからプログラマーの友人であるエディタで自動補完を試してみます。
関数の最初のパラメータ`first_name`を入力し、ドット(`.`)を入力してから、`Ctrl+Space`を押すと補完が実行されます。
関数の最初のパラメータ `first_name` を入力し、ドット(`.`)を入力してから、`Ctrl+Space` を押すと補完が実行されます。
しかし、悲しいことに、これはなんの役にも立ちません:
@ -78,7 +78,7 @@ John Doe
それが「型ヒント」です:
{* ../../docs_src/python_types/tutorial002_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial002_py310.py hl[1] *}
これは、以下のようにデフォルト値を宣言するのと同じではありません:
@ -94,7 +94,7 @@ John Doe
しかし今、あなたが再びその関数を作成している最中に、型ヒントを使っていると想像してみてください。
同じタイミングで`Ctrl+Space`で自動補完を実行すると、以下のようになります:
同じタイミングで `Ctrl+Space` で自動補完を実行すると、以下のようになります:
<img src="/img/python-types/image02.png">
@ -106,15 +106,15 @@ John Doe
この関数を見てください。すでに型ヒントを持っています:
{* ../../docs_src/python_types/tutorial003_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial003_py310.py hl[1] *}
エディタは変数の型を知っているので、補完だけでなく、エラーチェックをすることもできます:
<img src="/img/python-types/image04.png">
これで`age`を`str(age)`で文字列に変換して修正する必要があることがわかります:
これで `age` `str(age)` で文字列に変換して修正する必要があることがわかります:
{* ../../docs_src/python_types/tutorial004_py39.py hl[2] *}
{* ../../docs_src/python_types/tutorial004_py310.py hl[2] *}
## 型の宣言 { #declaring-types }
@ -124,7 +124,7 @@ John Doe
### 単純な型 { #simple-types }
`str`だけでなく、Pythonの標準的な型すべてを宣言できます。
`str` だけでなく、Python の標準的な型すべてを宣言できます。
例えば、以下を使用可能です:
@ -133,51 +133,54 @@ John Doe
* `bool`
* `bytes`
{* ../../docs_src/python_types/tutorial005_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial005_py310.py hl[1] *}
### 型パラメータを持つジェネリック型 { #generic-types-with-type-parameters }
### `typing` モジュール { #typing-module }
データ構造の中には、`dict`、`list`、`set`、`tuple`のように他の値を含むことができるものがあります。また内部の値も独自の型を持つことができます。
いくつかの追加のユースケースでは、標準ライブラリの `typing` モジュールから何かをインポートする必要があるかもしれません。例えば「任意の型」を受け付けることを宣言したい場合、`typing` の `Any` を使えます:
内部の型を持つこれらの型は「**generic**」型と呼ばれます。そして、内部の型も含めて宣言することが可能です。
```python
from typing import Any
これらの型や内部の型を宣言するには、Pythonの標準モジュール`typing`を使用できます。これらの型ヒントをサポートするために特別に存在しています。
#### 新しいPythonバージョン { #newer-versions-of-python }
def some_function(data: Any):
print(data)
```
`typing`を使う構文は、Python 3.6から最新バージョンまでPython 3.9、Python 3.10などを含む)すべてのバージョンと **互換性** があります。
### ジェネリック型 { #generic-types }
Pythonが進化するにつれ、**新しいバージョン** ではこれらの型アノテーションへのサポートが改善され、多くの場合、型アノテーションを宣言するために`typing`モジュールをインポートして使う必要すらなくなります。
一部の型は、角括弧内で「型パラメータ」を受け取り、内部の型を定義できます。例えば「文字列のリスト」は `list[str]` として宣言します。
プロジェクトでより新しいPythonバージョンを選べるなら、その追加のシンプルさを活用できます。
このように型パラメータを取れる型は **Generic types**(ジェネリクス)と呼ばれます。
ドキュメント全体で、Pythonの各バージョンと互換性のある例差分がある場合を示しています。
次の組み込み型をジェネリクスとして(角括弧と内部の型で)使えます:
例えば「**Python 3.6+**」はPython 3.6以上3.7、3.8、3.9、3.10などを含む)と互換性があることを意味します。また「**Python 3.9+**」はPython 3.9以上3.10などを含む)と互換性があることを意味します。
**最新のPythonバージョン** を使えるなら、最新バージョン向けの例を使ってください。例えば「**Python 3.10+**」のように、それらは **最良かつ最もシンプルな構文** になります。
* `list`
* `tuple`
* `set`
* `dict`
#### List { #list }
例えば、`str`の`list`の変数を定義してみましょう。
例えば、`str` `list` の変数を定義してみましょう。
同じコロン(`:`)の構文で変数を宣言します。
型として、`list`を指定します。
型として、`list` を指定します。
リストはいくつかの内部の型を含む型なので、それらを角括弧で囲みます:
{* ../../docs_src/python_types/tutorial006_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial006_py310.py hl[1] *}
/// info | 情報
角括弧内の内部の型は「型パラメータ」と呼ばれています。
この場合、`str`は`list`に渡される型パラメータです。
この場合、`str` `list` に渡される型パラメータです。
///
つまり: 変数`items`は`list`であり、このリストの各項目は`str`です。
つまり: 変数 `items` `list` であり、このリストの各項目は `str` です。
そうすることで、エディタはリストの項目を処理している間にもサポートを提供できます。
@ -185,78 +188,54 @@ Pythonが進化するにつれ、**新しいバージョン** ではこれらの
型がなければ、それはほぼ不可能です。
変数`item`はリスト`items`の要素の一つであることに注意してください。
変数 `item` はリスト `items` の要素の一つであることに注意してください。
それでも、エディタはそれが`str`であることを知っていて、そのためのサポートを提供しています。
それでも、エディタはそれが `str` であることを知っていて、そのためのサポートを提供しています。
#### Tuple と Set { #tuple-and-set }
`tuple`と`set`の宣言も同様です:
`tuple` `set` の宣言も同様です:
{* ../../docs_src/python_types/tutorial007_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial007_py310.py hl[1] *}
つまり:
* 変数`items_t`は`int`、別の`int`、`str`の3つの項目を持つ`tuple`です。
* 変数`items_s`は`set`であり、その各項目は`bytes`型です。
* 変数 `items_t` `int`、別の `int`、`str` 3 つの項目を持つ `tuple` です。
* 変数 `items_s` `set` であり、その各項目は `bytes` 型です。
#### Dict { #dict }
`dict`を定義するには、カンマ区切りで2つの型パラメータを渡します。
`dict` を定義するには、カンマ区切りで 2 つの型パラメータを渡します。
最初の型パラメータは`dict`のキーです。
最初の型パラメータは `dict` のキーです。
2番目の型パラメータは`dict`の値です:
2 番目の型パラメータは `dict` の値です:
{* ../../docs_src/python_types/tutorial008_py39.py hl[1] *}
{* ../../docs_src/python_types/tutorial008_py310.py hl[1] *}
つまり:
* 変数`prices`は`dict`です:
* この`dict`のキーは`str`型です(例えば、各項目の名前)。
* この`dict`の値は`float`型です(例えば、各項目の価格)。
* 変数 `prices` `dict` です:
* この `dict` のキーは `str` 型です(例えば、各項目の名前)。
* この `dict` の値は `float` 型です(例えば、各項目の価格)。
#### Union { #union }
変数が**複数の型のいずれか**になり得ることを宣言できます。例えば、`int`または`str`です。
変数が **複数の型のいずれか** になり得ることを宣言できます。例えば、`int` または `str` です。
Python 3.6以上Python 3.10を含む)では、`typing`の`Union`型を使い、角括弧の中に受け付ける可能性のある型を入れられます。
それを定義するには、両方の型を区切るために <dfn title="「ビット単位の OR 演算子」とも呼ばれますが、ここでの意味とは関係ありません。">縦棒(`|`</dfn> を使います。
Python 3.10では、受け付ける可能性のある型を<abbr title='also called "bitwise or operator", but that meaning is not relevant here'>縦棒(`|`</abbr>で区切って書ける **新しい構文** もあります。
//// tab | Python 3.10+
これは「ユニオンunion」と呼ばれます。変数がそれら 2 つの型の集合の和集合のいずれかになり得るからです。
```Python hl_lines="1"
{!> ../../docs_src/python_types/tutorial008b_py310.py!}
```
////
これは `item``int` または `str` になり得ることを意味します.
//// tab | Python 3.9+
#### `None` の可能性 { #possibly-none }
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial008b_py39.py!}
```
////
どちらの場合も、`item`は`int`または`str`になり得ることを意味します。
#### `None`の可能性 { #possibly-none }
値が`str`のような型を持つ可能性がある一方で、`None`にもなり得ることを宣言できます。
Python 3.6以上Python 3.10を含む)では、`typing`モジュールから`Optional`をインポートして使うことで宣言できます。
```Python hl_lines="1 4"
{!../../docs_src/python_types/tutorial009_py39.py!}
```
ただの`str`の代わりに`Optional[str]`を使用することで、値が常に`str`であると仮定しているときに、実際には`None`である可能性もあるというエラーをエディタが検出するのに役立ちます。
`Optional[Something]`は実際には`Union[Something, None]`のショートカットで、両者は等価です。
これは、Python 3.10では`Something | None`も使えることを意味します:
値が `str` のような型を持つ可能性がある一方で、`None` にもなり得ることを宣言できます。
//// tab | Python 3.10+
@ -266,120 +245,31 @@ Python 3.6以上Python 3.10を含む)では、`typing`モジュールから
////
//// tab | Python 3.9+
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009_py39.py!}
```
////
//// tab | Python 3.9+ alternative
```Python hl_lines="1 4"
{!> ../../docs_src/python_types/tutorial009b_py39.py!}
```
////
#### `Union`または`Optional`の使用 { #using-union-or-optional }
Python 3.10未満のバージョンを使っている場合、これは私のとても **主観的** な観点からのヒントです:
* 🚨 `Optional[SomeType]`は避けてください
* 代わりに ✨ **`Union[SomeType, None]`を使ってください** ✨
どちらも等価で、内部的には同じですが、`Optional`より`Union`をおすすめします。というのも「**optional**」という単語は値がオプションであることを示唆するように見えますが、実際には「`None`になり得る」という意味であり、オプションではなく必須である場合でもそうだからです。
`Union[SomeType, None]`のほうが意味がより明示的だと思います。
これは言葉や名前の話にすぎません。しかし、その言葉はあなたやチームメイトがコードをどう考えるかに影響し得ます。
例として、この関数を見てみましょう:
{* ../../docs_src/python_types/tutorial009c_py39.py hl[1,4] *}
パラメータ`name`は`Optional[str]`として定義されていますが、**オプションではありません**。そのパラメータなしで関数を呼び出せません:
```Python
say_hi() # Oh, no, this throws an error! 😱
```
`name`パラメータはデフォルト値がないため、**依然として必須***optional*ではない)です。それでも、`name`は値として`None`を受け付けます:
```Python
say_hi(name=None) # This works, None is valid 🎉
```
良い知らせとして、Python 3.10になればその心配は不要です。型のユニオンを定義するために`|`を単純に使えるからです:
{* ../../docs_src/python_types/tutorial009c_py310.py hl[1,4] *}
そして、`Optional`や`Union`のような名前について心配する必要もなくなります。😎
#### ジェネリック型 { #generic-types }
角括弧で型パラメータを取るこれらの型は、例えば次のように **Generic types** または **Generics** と呼ばれます:
//// tab | Python 3.10+
同じ組み込み型をジェネリクスとして(角括弧と内部の型で)使えます:
* `list`
* `tuple`
* `set`
* `dict`
また、これまでのPythonバージョンと同様に、`typing`モジュールから:
* `Union`
* `Optional`
* ...and others.
Python 3.10では、ジェネリクスの`Union`や`Optional`を使う代替として、型のユニオンを宣言するために<abbr title='also called "bitwise or operator", but that meaning is not relevant here'>縦棒(`|`</abbr>を使えます。これはずっと良く、よりシンプルです。
////
//// tab | Python 3.9+
同じ組み込み型をジェネリクスとして(角括弧と内部の型で)使えます:
* `list`
* `tuple`
* `set`
* `dict`
そして`typing`モジュールのジェネリクス:
* `Union`
* `Optional`
* ...and others.
////
ただの `str` の代わりに `str | None` を使用することで、値が常に `str` であると仮定しているときに、実際には `None` である可能性もあるというエラーをエディタが検出するのに役立ちます。
### 型としてのクラス { #classes-as-types }
変数の型としてクラスを宣言することもできます。
名前を持つ`Person`クラスがあるとしましょう:
名前を持つ `Person` クラスがあるとしましょう:
{* ../../docs_src/python_types/tutorial010_py39.py hl[1:3] *}
{* ../../docs_src/python_types/tutorial010_py310.py hl[1:3] *}
変数を`Person`型として宣言できます:
変数を `Person` 型として宣言できます:
{* ../../docs_src/python_types/tutorial010_py39.py hl[6] *}
{* ../../docs_src/python_types/tutorial010_py310.py hl[6] *}
そして、再び、すべてのエディタのサポートを得ることができます:
<img src="/img/python-types/image06.png">
これは「`one_person`はクラス`Person`の**インスタンス**である」ことを意味します。
これは「`one_person` はクラス `Person`**インスタンス** である」ことを意味します。
「`one_person`は`Person`という名前の**クラス**である」という意味ではありません。
「`one_person` は `Person` という名前の **クラス** である」という意味ではありません。
## Pydanticのモデル { #pydantic-models }
## Pydantic のモデル { #pydantic-models }
<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> はデータ検証を行うためのPythonライブラリです。
<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> はデータ検証を行うための Python ライブラリです。
データの「形」を属性付きのクラスとして宣言します。
@ -389,53 +279,47 @@ Python 3.10では、ジェネリクスの`Union`や`Optional`を使う代替と
また、その結果のオブジェクトですべてのエディタのサポートを受けることができます。
Pydanticの公式ドキュメントからの例:
Pydantic の公式ドキュメントからの例:
{* ../../docs_src/python_types/tutorial011_py310.py *}
/// info | 情報
<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydanticの詳細はドキュメントを参照してください</a>
<a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic の詳細はドキュメントを参照してください</a>
///
**FastAPI** はすべてPydanticをベースにしています。
**FastAPI** はすべて Pydantic をベースにしています。
すべてのことは[チュートリアル - ユーザーガイド](tutorial/index.md){.internal-link target=_blank}で実際に見ることができます。
/// tip | 豆知識
Pydanticには、デフォルト値なしで`Optional`または`Union[Something, None]`を使った場合の特別な挙動があります。詳細はPydanticドキュメントの<a href="https://docs.pydantic.dev/2.3/usage/models/#required-fields" class="external-link" target="_blank">Required Optional fields</a>を参照してください。
///
すべてのことは [チュートリアル - ユーザーガイド](tutorial/index.md){.internal-link target=_blank} で実際に見ることができます。
## メタデータアノテーション付き型ヒント { #type-hints-with-metadata-annotations }
Pythonには、`Annotated`を使って型ヒントに**追加の<abbr title="Data about the data, in this case, information about the type, e.g. a description.">メタデータ</abbr>**を付与できる機能もあります。
Python には、`Annotated` を使って型ヒントに **追加の <dfn title="データに関するデータ。この場合は型に関する情報(例えば説明)。">メタデータ</dfn>** を付与できる機能もあります。
Python 3.9以降、`Annotated`は標準ライブラリの一部なので、`typing`からインポートできます。
`Annotated``typing` からインポートできます。
{* ../../docs_src/python_types/tutorial013_py39.py hl[1,4] *}
{* ../../docs_src/python_types/tutorial013_py310.py hl[1,4] *}
Python自体は、この`Annotated`で何かをするわけではありません。また、エディタや他のツールにとっても、型は依然として`str`です。
Python 自体は、この `Annotated` で何かをするわけではありません。また、エディタや他のツールにとっても、型は依然として `str` です。
しかし、`Annotated`内のこのスペースを使って、アプリケーションをどのように動作させたいかについての追加メタデータを **FastAPI** に提供できます。
しかし、`Annotated` 内のこのスペースを使って、アプリケーションをどのように動作させたいかについての追加メタデータを **FastAPI** に提供できます。
覚えておくべき重要な点は、`Annotated`に渡す**最初の*型パラメータ***が**実際の型**であることです。残りは、他のツール向けのメタデータにすぎません。
覚えておくべき重要な点は、`Annotated` に渡す **最初の「型パラメータ」****実際の型** であることです。残りは、他のツール向けのメタデータにすぎません。
今のところは、`Annotated`が存在し、それが標準のPythonであることを知っておけば十分です。😎
今のところは、`Annotated` が存在し、それが標準の Python であることを知っておけば十分です。😎
後で、これがどれほど**強力**になり得るかを見ることになります。
後で、これがどれほど **強力** になり得るかを見ることになります。
/// tip | 豆知識
これが **標準のPython** であるという事実は、エディタで、使用しているツール(コードの解析やリファクタリングなど)とともに、**可能な限り最高の開発体験**が得られることを意味します。 ✨
これが **標準の Python** であるという事実は、エディタで、使用しているツール(コードの解析やリファクタリングなど)とともに、**可能な限り最高の開発体験** が得られることを意味します。 ✨
また、あなたのコードが他の多くのPythonツールやライブラリとも非常に互換性が高いことも意味します。 🚀
また、あなたのコードが他の多くの Python ツールやライブラリとも非常に互換性が高いことも意味します。 🚀
///
## **FastAPI**での型ヒント { #type-hints-in-fastapi }
## **FastAPI** での型ヒント { #type-hints-in-fastapi }
**FastAPI** はこれらの型ヒントを利用していくつかのことを行います。
@ -450,15 +334,15 @@ Python自体は、この`Annotated`で何かをするわけではありません
* **データの変換**: リクエストから必要な型にデータを変換します。
* **データの検証**: 各リクエストから来るデータについて:
* データが無効な場合にクライアントに返される **自動エラー** を生成します。
* OpenAPIを使用してAPIを**ドキュメント化**します:
* OpenAPI を使用して API **ドキュメント化** します:
* これは自動の対話型ドキュメントのユーザーインターフェイスで使われます。
すべてが抽象的に聞こえるかもしれません。心配しないでください。 この全ての動作は [チュートリアル - ユーザーガイド](tutorial/index.md){.internal-link target=_blank}で見ることができます。
すべてが抽象的に聞こえるかもしれません。心配しないでください。 この全ての動作は [チュートリアル - ユーザーガイド](tutorial/index.md){.internal-link target=_blank} で見ることができます。
重要なのは、Pythonの標準的な型を使うことで、クラスやデコレータなどを追加するのではなく1つの場所で **FastAPI** が多くの作業を代わりにやってくれているということです。
重要なのは、Python の標準的な型を使うことで、クラスやデコレータなどを追加するのではなく1 つの場所で **FastAPI** が多くの作業を代わりにやってくれているということです。
/// info | 情報
すでにすべてのチュートリアルを終えて、型についての詳細を見るためにこのページに戻ってきた場合は、良いリソースとして<a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">`mypy`の「チートシート」</a>があります。
すでにすべてのチュートリアルを終えて、型についての詳細を見るためにこのページに戻ってきた場合は、良いリソースとして <a href="https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html" class="external-link" target="_blank">`mypy` の「チートシート」</a> があります。
///

View File

@ -0,0 +1,3 @@
# リソース { #resources }
追加リソース、外部リンクなど。✈️

View File

@ -0,0 +1,11 @@
/// details | 🌐 AI と人間による翻訳
この翻訳は、人間のガイドに基づいて AI によって作成されました。🤝
原文の意図を取り違えていたり、不自然な表現になっている可能性があります。🤖
[AI LLM をより適切に誘導するのを手伝う](https://fastapi.tiangolo.com/ja/contributing/#translations) ことで、この翻訳を改善できます。
[英語版](ENGLISH_VERSION_URL)
///

View File

@ -15,7 +15,7 @@
まず初めに、`BackgroundTasks` をインポートし、`BackgroundTasks` の型宣言と共に、*path operation function* のパラメーターを定義します:
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *}
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[1,13] *}
**FastAPI** は、`BackgroundTasks` 型のオブジェクトを作成し、そのパラメーターに渡します。
@ -31,13 +31,13 @@
また、書き込み操作では `async``await` を使用しないため、通常の `def` で関数を定義します。
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *}
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[6:9] *}
## バックグラウンドタスクの追加 { #add-the-background-task }
*path operation function* 内で、`.add_task()` メソッドを使用してタスク関数を *background tasks* オブジェクトに渡します。
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *}
{* ../../docs_src/background_tasks/tutorial001_py310.py hl[14] *}
`.add_task()` は以下の引数を受け取ります:

View File

@ -0,0 +1,504 @@
# 大規模アプリケーション - 複数ファイル { #bigger-applications-multiple-files }
アプリケーションや Web API を作る場合、すべてを1つのファイルに収められることはほとんどありません。
**FastAPI** は、柔軟性を保ったままアプリケーションを構造化できる便利なツールを提供します。
/// info | 情報
Flask 出身であれば、Flask の Blueprint に相当します。
///
## 例のファイル構成 { #an-example-file-structure }
次のようなファイル構成があるとします:
```
.
├── app
│   ├── __init__.py
│   ├── main.py
│   ├── dependencies.py
│   └── routers
│   │ ├── __init__.py
│   │ ├── items.py
│   │ └── users.py
│   └── internal
│   ├── __init__.py
│   └── admin.py
```
/// tip | 豆知識
複数の `__init__.py` ファイルがあります: 各ディレクトリやサブディレクトリに1つずつです。
これにより、あるファイルから別のファイルへコードをインポートできます。
例えば、`app/main.py` では次のように書けます:
```
from app.routers import items
```
///
* `app` ディレクトリはすべてを含みます。そして空のファイル `app/__init__.py` があり、「Python パッケージ」「Python モジュール」の集合): `app` です。
* `app/main.py` ファイルがあります。Python パッケージ(`__init__.py` のあるディレクトリ)の中にあるため、そのパッケージの「モジュール」: `app.main` です。
* `app/dependencies.py` ファイルもあり、`app/main.py` と同様に「モジュール」: `app.dependencies` です。
* `app/routers/` サブディレクトリに別の `__init__.py` があるので、「Python サブパッケージ」: `app.routers` です。
* `app/routers/items.py` はパッケージ `app/routers/` 内のファイルなので、サブモジュール: `app.routers.items` です。
* `app/routers/users.py` も同様で、別のサブモジュール: `app.routers.users` です。
* `app/internal/` サブディレクトリにも `__init__.py` があるので、別の「Python サブパッケージ」: `app.internal` です。
* `app/internal/admin.py` は別のサブモジュール: `app.internal.admin` です。
<img src="/img/tutorial/bigger-applications/package.drawio.svg">
同じファイル構成にコメントを付けると次のとおりです:
```bash
.
├── app # "app" is a Python package
│   ├── __init__.py # this file makes "app" a "Python package"
│   ├── main.py # "main" module, e.g. import app.main
│   ├── dependencies.py # "dependencies" module, e.g. import app.dependencies
│   └── routers # "routers" is a "Python subpackage"
│   │ ├── __init__.py # makes "routers" a "Python subpackage"
│   │ ├── items.py # "items" submodule, e.g. import app.routers.items
│   │ └── users.py # "users" submodule, e.g. import app.routers.users
│   └── internal # "internal" is a "Python subpackage"
│   ├── __init__.py # makes "internal" a "Python subpackage"
│   └── admin.py # "admin" submodule, e.g. import app.internal.admin
```
## `APIRouter` { #apirouter }
ユーザーだけを扱うファイルが `/app/routers/users.py` のサブモジュールだとします。
ユーザーに関連する *path operations* をほかのコードから分離して整理したいはずです。
ただし、同じ **FastAPI** アプリケーション / Web API同じ「Python パッケージ」の一部)である点は変わりません。
そのモジュールで `APIRouter` を使って *path operations* を作成できます。
### `APIRouter` のインポート { #import-apirouter }
クラス `FastAPI` と同様にインポートし、「インスタンス」を作成します:
{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[1,3] title["app/routers/users.py"] *}
### `APIRouter` での *path operations* { #path-operations-with-apirouter }
これを使って *path operations* を宣言します。
使い方は `FastAPI` クラスと同じです:
{* ../../docs_src/bigger_applications/app_an_py310/routers/users.py hl[6,11,16] title["app/routers/users.py"] *}
`APIRouter` は「ミニ `FastAPI`」のようなクラスと考えられます。
同じオプションがすべてサポートされています。
同じ `parameters`、`responses`、`dependencies`、`tags` などが使えます。
/// tip | 豆知識
この例では変数名は `router` ですが、任意の名前を付けられます。
///
この `APIRouter` をメインの `FastAPI` アプリに取り込みますが、その前に依存関係と別の `APIRouter` を確認します。
## 依存関係 { #dependencies }
アプリケーションの複数箇所で使う依存関係が必要になります。
そのため、専用の `dependencies` モジュール(`app/dependencies.py`)に置きます。
ここではカスタムヘッダー `X-Token` を読む簡単な依存関係を使います:
{* ../../docs_src/bigger_applications/app_an_py310/dependencies.py hl[3,6:8] title["app/dependencies.py"] *}
/// tip | 豆知識
この例を簡単にするために架空のヘッダーを使っています。
しかし実際には、組み込みの [Security utilities](security/index.md){.internal-link target=_blank} を使う方が良い結果になります。
///
## 別モジュールでの `APIRouter` { #another-module-with-apirouter }
アプリケーションの「items」を扱うエンドポイントが `app/routers/items.py` のモジュールにあるとします。
次の *path operations* があります:
* `/items/`
* `/items/{item_id}`
構造は `app/routers/users.py` と同じです。
しかし、もう少し賢くしてコードを少し簡潔にしたいところです。
このモジュールのすべての *path operations* には同じものがあると分かっています:
* パスの `prefix`: `/items`
* `tags`1つのタグ: `items`
* 追加の `responses`
* `dependencies`: 先ほど作成した `X-Token` の依存関係が必要
そこで、各 *path operation* に個別に追加する代わりに、これらを `APIRouter` に追加できます。
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[5:10,16,21] title["app/routers/items.py"] *}
*path operation* のパスは次のように `/` で始める必要があるため:
```Python hl_lines="1"
@router.get("/{item_id}")
async def read_item(item_id: str):
...
```
...prefix の末尾に `/` を含めてはいけません。
この場合の prefix は `/items` です。
また、`tags` のリストや追加の `responses` を、このルーターに含まれるすべての *path operations* に適用するよう追加できます。
さらに `dependencies` のリストを追加できます。これはこのルーター内のすべての *path operations* に追加され、それらへの各リクエストごとに実行・解決されます。
/// tip | 豆知識
[*path operation デコレータ*の依存関係](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank} と同様に、*path operation 関数*には値は渡されない点に注意してください。
///
最終的に、item のパスは次のとおりになります:
* `/items/`
* `/items/{item_id}`
...意図したとおりです。
* これらには、文字列 `"items"` を1つ含むタグのリストが付きます。
* これらの「タグ」は、OpenAPI を使う)自動インタラクティブドキュメントで特に有用です。
* すべてに事前定義した `responses` が含まれます。
* これらすべての *path operations* では、実行前に `dependencies` のリストが評価・実行されます。
* 特定の *path operation* に依存関係を宣言した場合は、**それらも実行されます**。
* ルーターの依存関係が先に実行され、その後に[デコレータ内の `dependencies`](dependencies/dependencies-in-path-operation-decorators.md){.internal-link target=_blank}、次に通常のパラメータ依存関係が続きます。
* [`scopes` を伴う `Security` 依存関係](../advanced/security/oauth2-scopes.md){.internal-link target=_blank} を追加することもできます。
/// tip | 豆知識
`APIRouter``dependencies` を置くことで、*path operations* のグループ全体に認証を要求する、といった用途に使えます。個々の *path operation* に依存関係を追加していなくても構いません。
///
/// check | 確認
`prefix`、`tags`、`responses`、`dependencies` の各パラメータは(ほかの多くのケースと同様に)コード重複を避けるための **FastAPI** の機能です。
///
### 依存関係をインポート { #import-the-dependencies }
このコードはモジュール `app.routers.items`(ファイル `app/routers/items.py`)内にあります。
そして依存関係の関数はモジュール `app.dependencies`(ファイル `app/dependencies.py`)から取得する必要があります。
そこで、依存関係には `..` を使った相対インポートを使います:
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[3] title["app/routers/items.py"] *}
#### 相対インポートの仕組み { #how-relative-imports-work }
/// tip | 豆知識
インポートの仕組みを十分理解している場合は、次の節に進んでください。
///
ドット1つ `.` を使うと、次のような意味になります:
```Python
from .dependencies import get_token_header
```
意味:
* このモジュール(`app/routers/items.py`)が存在する同じパッケージ(ディレクトリ `app/routers/`)から開始し...
* モジュール `dependencies`(仮想的には `app/routers/dependencies.py`)を探し...
* そこから関数 `get_token_header` をインポートする。
しかしそのファイルは存在せず、実際の依存関係は `app/dependencies.py` にあります。
アプリ/ファイル構成がどうなっていたかを思い出してください:
<img src="/img/tutorial/bigger-applications/package.drawio.svg">
---
ドット2つ `..` を使うと、次のようになります:
```Python
from ..dependencies import get_token_header
```
意味:
* このモジュール(`app/routers/items.py`)が存在する同じパッケージ(ディレクトリ `app/routers/`)から開始し...
* 親パッケージ(ディレクトリ `app/`)に移動し...
* そこでモジュール `dependencies`(ファイル `app/dependencies.py`)を探し...
* そこから関数 `get_token_header` をインポートする。
これは正しく動作します! 🎉
---
同様に、ドット3つ `...` を使うと:
```Python
from ...dependencies import get_token_header
```
意味:
* このモジュール(`app/routers/items.py`)が存在する同じパッケージ(ディレクトリ `app/routers/`)から開始し...
* 親パッケージ(ディレクトリ `app/`)に移動し...
* さらにその親パッケージに移動しようとします(`app` は最上位なので親パッケージはありません 😱)...
* そこでモジュール `dependencies`(ファイル `app/dependencies.py`)を探し...
* そこから関数 `get_token_header` をインポートする。
これは `app/` より上位のパッケージ(独自の `__init__.py` を持つ)を参照することになります。しかしそのようなものはありません。そのため、この例ではエラーになります。🚨
これで仕組みが分かったので、どれほど複雑でも自分のアプリで相対インポートを使えます。🤓
### カスタムの `tags`、`responses`、`dependencies` を追加 { #add-some-custom-tags-responses-and-dependencies }
`APIRouter` に追加済みなので、各 *path operation*`/items` の prefix や `tags=["items"]` を付けていません。
しかし、特定の *path operation* に適用される _追加の_ `tags` や、その *path operation* 固有の追加の `responses` を加えることはできます:
{* ../../docs_src/bigger_applications/app_an_py310/routers/items.py hl[30:31] title["app/routers/items.py"] *}
/// tip | 豆知識
この最後の *path operation* は、`["items", "custom"]` のタグの組み合わせを持ちます。
またドキュメントには `404``403` の両方のレスポンスが表示されます。
///
## メインの `FastAPI` { #the-main-fastapi }
次に、`app/main.py` のモジュールを見ていきます。
ここでクラス `FastAPI` をインポートして使用します。
これはすべてをまとめるアプリケーションのメインファイルになります。
そして大部分のロジックはそれぞれの専用モジュールに置かれるため、メインファイルはかなりシンプルになります。
### `FastAPI` のインポート { #import-fastapi }
通常どおり `FastAPI` クラスをインポートして作成します。
さらに、各 `APIRouter` の依存関係と組み合わされる[グローバル依存関係](dependencies/global-dependencies.md){.internal-link target=_blank}も宣言できます:
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[1,3,7] title["app/main.py"] *}
### `APIRouter` のインポート { #import-the-apirouter }
次に、`APIRouter` を持つ他のサブモジュールをインポートします:
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[4:5] title["app/main.py"] *}
`app/routers/users.py``app/routers/items.py` は同じ Python パッケージ `app` のサブモジュールなので、1つのドット `.` を使った「相対インポート」でインポートできます。
### インポートの動作 { #how-the-importing-works }
次の部分:
```Python
from .routers import items, users
```
は次の意味です:
* このモジュール(`app/main.py`)が存在する同じパッケージ(ディレクトリ `app/`)から開始し...
* サブパッケージ `routers`(ディレクトリ `app/routers/`)を探し...
* そこからサブモジュール `items`(ファイル `app/routers/items.py`)と `users`(ファイル `app/routers/users.py`)をインポートする...
モジュール `items` には変数 `router``items.router`)があります。これは `app/routers/items.py` で作成した `APIRouter` オブジェクトと同じものです。
モジュール `users` についても同様です。
次のようにインポートすることもできます:
```Python
from app.routers import items, users
```
/// info | 情報
最初のバージョンは「相対インポート」です:
```Python
from .routers import items, users
```
2つ目のバージョンは「絶対インポート」です:
```Python
from app.routers import items, users
```
Python のパッケージとモジュールについて詳しくは、<a href="https://docs.python.org/3/tutorial/modules.html" class="external-link" target="_blank">公式の Python モジュールに関するドキュメント</a>をご覧ください。
///
### 名前衝突の回避 { #avoid-name-collisions }
サブモジュール `items` の変数 `router` だけをインポートするのではなく、サブモジュール自体を直接インポートしています。
これは、サブモジュール `users` にも `router` という変数があるためです。
もし次のように続けてインポートした場合:
```Python
from .routers.items import router
from .routers.users import router
```
`users``router``items` のものを上書きしてしまい、同時に両方を使えなくなります。
同じファイルで両方を使えるようにするため、サブモジュールを直接インポートします:
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[5] title["app/main.py"] *}
### `users``items``APIRouter` を取り込む { #include-the-apirouters-for-users-and-items }
では、サブモジュール `users``items` から `router` を取り込みます:
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[10:11] title["app/main.py"] *}
/// info | 情報
`users.router` は、ファイル `app/routers/users.py` 内の `APIRouter` を含みます。
`items.router` は、ファイル `app/routers/items.py` 内の `APIRouter` を含みます。
///
`app.include_router()` を使って、各 `APIRouter` をメインの `FastAPI` アプリケーションに追加できます。
そのルーターのすべてのルートがアプリに含まれます。
/// note | 技術詳細
実際には、`APIRouter` で宣言された各 *path operation* ごとに内部的に *path operation* が作成されます。
つまり裏側では、すべてが同じ単一のアプリであるかのように動作します。
///
/// check | 確認
ルーターを取り込んでもパフォーマンスを心配する必要はありません。
これは起動時にマイクロ秒で行われます。
したがってパフォーマンスには影響しません。⚡
///
### カスタムの `prefix`、`tags`、`responses`、`dependencies` 付きで `APIRouter` を取り込む { #include-an-apirouter-with-a-custom-prefix-tags-responses-and-dependencies }
あなたの組織から `app/internal/admin.py` ファイルが提供されたとしましょう。
そこには、組織が複数プロジェクトで共有している管理用の *path operations* を持つ `APIRouter` が含まれています。
この例ではとてもシンプルですが、組織内の他プロジェクトと共有しているため、`APIRouter` 自体を直接変更して `prefix`、`dependencies`、`tags` などを追加できないとします:
{* ../../docs_src/bigger_applications/app_an_py310/internal/admin.py hl[3] title["app/internal/admin.py"] *}
それでも、`APIRouter` を取り込む際にカスタムの `prefix` を設定してすべての *path operations*`/admin` で始めたい、既存の `dependencies` で保護したい、さらに `tags``responses` も含めたいとします。
元の `APIRouter` を変更することなく、`app.include_router()` にこれらのパラメータを渡すことで宣言できます:
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[14:17] title["app/main.py"] *}
このようにすると、元の `APIRouter` は未変更のままなので、同じ `app/internal/admin.py` ファイルを組織内の他プロジェクトとも引き続き共有できます。
結果として、このアプリ内では `admin` モジュールの各 *path operation* が次のようになります:
* prefix は `/admin`
* タグは `admin`
* 依存関係は `get_token_header`
* レスポンスは `418` 🍵
ただし、これはこのアプリ内のその `APIRouter` にのみ影響し、それを使用する他のコードには影響しません。
例えば、他のプロジェクトでは同じ `APIRouter` を別の認証方式で使うこともできます。
### *path operation* を追加 { #include-a-path-operation }
`FastAPI` アプリに *path operations* を直接追加することもできます。
ここでは(できることを示すためだけに)追加します 🤷:
{* ../../docs_src/bigger_applications/app_an_py310/main.py hl[21:23] title["app/main.py"] *}
そして、`app.include_router()` で追加したほかの *path operations* と一緒に正しく動作します。
/// info | 非常に技術的な詳細
注記: これは非常に技術的な詳細で、**読み飛ばして構いません**。
---
`APIRouter` は「マウント」されておらず、アプリケーションの他部分から分離されていません。
これは、それらの *path operations* を OpenAPI スキーマやユーザーインターフェースに含めたいからです。
完全に分離して独立に「マウント」できないため、*path operations* は直接取り込まれるのではなく「クローン(再作成)」されます。
///
## 自動APIドキュメントの確認 { #check-the-automatic-api-docs }
アプリを実行します:
<div class="termy">
```console
$ fastapi dev app/main.py
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
</div>
そして <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> を開きます。
すべてのサブモジュール由来のパスを含む自動 API ドキュメントが表示され、正しいパス(および prefixと正しいタグが使われているのが分かります:
<img src="/img/tutorial/bigger-applications/image01.png">
## 同じルーターを異なる `prefix` で複数回取り込む { #include-the-same-router-multiple-times-with-different-prefix }
同じルーターに対して、異なる prefix で `.include_router()` を複数回使うこともできます。
例えば、同じ API を `/api/v1``/api/latest` のように異なる prefix で公開する場合に役立ちます。
高度な使い方なので不要かもしれませんが、必要な場合に備えて用意されています。
## `APIRouter` を別の `APIRouter` に取り込む { #include-an-apirouter-in-another }
`APIRouter``FastAPI` アプリケーションに取り込めるのと同じように、`APIRouter` を別の `APIRouter` に取り込むこともできます:
```Python
router.include_router(other_router)
```
`router``FastAPI` アプリに取り込む前にこれを実行して、`other_router` の *path operations* も含まれるようにしてください。

View File

@ -106,12 +106,6 @@
q: str | None = None
```
またはPython 3.10以上では:
```Python
q: Union[str, None] = None
```
例えば:
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}

View File

@ -164,7 +164,7 @@ images: list[Image]
以下のように:
{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *}
{* ../../docs_src/body_nested_models/tutorial008_py310.py hl[13] *}
## あらゆる場所でのエディタサポート { #editor-support-everywhere }
@ -194,7 +194,7 @@ Pydanticモデルではなく、`dict`を直接使用している場合はこの
この場合、`int`のキーと`float`の値を持つものであれば、どんな`dict`でも受け入れることができます:
{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *}
{* ../../docs_src/body_nested_models/tutorial009_py310.py hl[7] *}
/// tip | 豆知識

View File

@ -68,7 +68,7 @@
まとめると、部分的な更新を適用するには、次のようにします:
* (オプションで)`PUT`の代わりに`PATCH`を使用します。
* (オプションで)`PATCH`の代わりに`PUT`を使用します。
* 保存されているデータを取得します。
* そのデータをPydanticモデルにいれます。
* 入力モデルからデフォルト値を含まない`dict`を生成します(`exclude_unset`を使用します)。

View File

@ -74,7 +74,7 @@ APIはほとんどの場合 **レスポンス** ボディを送信する必要
* 受け取ったデータをパラメータ `item` に渡します。
* 関数内で `Item` 型として宣言したため、すべての属性とその型について、エディタサポート(補完など)も利用できます。
* モデル向けの <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> 定義を生成します。プロジェクトにとって意味があるなら、他の場所でも好きなように利用できます。
* それらのスキーマは生成されるOpenAPIスキーマの一部となり、自動ドキュメントの <abbr title="User Interfaces">UIs</abbr> で使用されます。
* それらのスキーマは生成されるOpenAPIスキーマの一部となり、自動ドキュメントの <abbr title="User Interfaces - ユーザーインターフェース">UIs</abbr> で使用されます。
## 自動ドキュメント { #automatic-docs }
@ -155,7 +155,7 @@ APIはほとんどの場合 **レスポンス** ボディを送信する必要
FastAPIは、デフォルト値 `= None` があるため、`q` の値が必須ではないことを認識します。
`str | None`Python 3.10+)や `Union[str, None]`Python 3.9+)の `Union` は、値が必須ではないことを判断するためにFastAPIでは使用されません。`= None` というデフォルト値があるため、必須ではないことを認識します。
`str | None` は、値が必須ではないことを判断するためにFastAPIでは使用されません。`= None` というデフォルト値があるため、必須ではないことを認識します。
しかし、型アノテーションを追加すると、エディタがより良いサポートを提供し、エラーを検出できるようになります。

View File

@ -46,7 +46,7 @@
特定の(あまり一般的ではないかもしれない)ケースで、受け付けるクッキーを**制限**する必要があるかもしれません。
あなたのAPIは独自の <abbr title="念のためですが、これはジョークです。クッキー同意とは関係ありませんが、APIでさえ不適切なクッキーを拒否できるとは愉快ですね。クッキーでも食べてください。🍪 (原文: This is a joke, just in case. It has nothing to do with cookie consents, but it's funny that even the API can now reject the poor cookies. Have a cookie. 🍪)">クッキー同意</abbr> を管理する能力を持っています。 🤪🍪
あなたのAPIは独自の <dfn title="念のためですが、これはジョークです。クッキー同意とは関係ありませんが、APIでさえ今やかわいそうなクッキーを拒否できるのは面白いですね。クッキーでもどうぞ。🍪">クッキー同意</dfn> を管理する能力を持っています。 🤪🍪
Pydanticのモデルの Configuration を利用して、 `extra` フィールドを `forbid` とすることができます。
@ -54,9 +54,9 @@ Pydanticのモデルの Configuration を利用して、 `extra` フィールド
もしクライアントが**余分なクッキー**を送ろうとすると、**エラー**レスポンスが返されます。
<abbr title="これもジョークです。気にしないでください。クッキーのお供にコーヒーでも飲んでください。☕ (原文: This is another joke. Don't pay attention to me. Have some coffee for your cookie. ☕)">どうせAPIに拒否されるのに</abbr>あなたの同意を得ようと精一杯努力する可哀想なクッキーバナーたち... 🍪
<dfn title="これもジョークです。気にしないでください。クッキーのお供にコーヒーでもどうぞ。☕">どうせAPIに拒否されるのに</dfn>あなたの同意を得ようと精一杯努力する可哀想なクッキーバナーたち... 🍪
例えば、クライアントがクッキー `santa_tracker``good-list-please` という値で送ろうとすると、`santa_tracker` という <abbr title="サンタはクッキー不足を良しとはしないでしょう。🎅 はい、クッキージョークはもう止めておきます。(原文: Santa disapproves the lack of cookies. 🎅 Okay, no more cookie jokes.">クッキーが許可されていない</abbr> ことを通知する**エラー**レスポンスが返されます:
例えば、クライアントがクッキー `santa_tracker``good-list-please` という値で送ろうとすると、`santa_tracker` という <dfn title="サンタはクッキー不足を良しとしません。🎅 はい、クッキージョークはこれでおしまい。">クッキーが許可されていない</dfn> ことを通知する**エラー**レスポンスが返されます:
```json
{
@ -73,4 +73,4 @@ Pydanticのモデルの Configuration を利用して、 `extra` フィールド
## まとめ { #summary }
**FastAPI**では、<abbr title="帰ってしまう前に最後のクッキーをどうぞ。🍪 (原文: Have a last cookie before you go. 🍪)">**クッキー**</abbr>を宣言するために、**Pydanticモデル**を使用できます。😎
**FastAPI**では、<dfn title="帰る前に最後のクッキーをどうぞ。🍪">**クッキー**</dfn>を宣言するために、**Pydanticモデル**を使用できます。😎

View File

@ -46,7 +46,7 @@
* 特定のHTTPメソッド (`POST`、`PUT`) またはワイルドカード `"*"` を使用してすべて許可。
* 特定のHTTPヘッダー、またはワイルドカード `"*"`を使用してすべて許可。
{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *}
{* ../../docs_src/cors/tutorial001_py310.py hl[2,6:11,13:19] *}
`CORSMiddleware` 実装で使用されるデフォルトのパラメータはデフォルトで制限が厳しいため、ブラウザがクロスドメインのコンテキストでそれらを使用できるようにするには、特定のオリジン、メソッド、またはヘッダーを明示的に有効にする必要があります。

View File

@ -6,7 +6,7 @@ Visual Studio CodeやPyCharmなどを使用して、エディター上でデバ
FastAPIアプリケーション上で、`uvicorn` を直接インポートして実行します:
{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *}
{* ../../docs_src/debugging/tutorial001_py310.py hl[1,15] *}
### `__name__ == "__main__"` について { #about-name-main }

View File

@ -101,7 +101,7 @@ FastAPIが実際にチェックしているのは、それが「呼び出し可
上のコードでは`CommonQueryParams`を2回書いていることに注目してください:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@ -109,7 +109,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
//// tab | Python 3.9+ 注釈なし
//// tab | Python 3.10+ 注釈なし
/// tip | 豆知識
@ -137,7 +137,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
この場合、以下にある最初の`CommonQueryParams`:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[CommonQueryParams, ...
@ -145,7 +145,7 @@ commons: Annotated[CommonQueryParams, ...
////
//// tab | Python 3.9+ 注釈なし
//// tab | Python 3.10+ 注釈なし
/// tip | 豆知識
@ -163,7 +163,7 @@ commons: CommonQueryParams ...
実際には以下のように書けばいいだけです:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[Any, Depends(CommonQueryParams)]
@ -171,7 +171,7 @@ commons: Annotated[Any, Depends(CommonQueryParams)]
////
//// tab | Python 3.9+ 注釈なし
//// tab | Python 3.10+ 注釈なし
/// tip | 豆知識
@ -197,7 +197,7 @@ commons = Depends(CommonQueryParams)
しかし、ここでは`CommonQueryParams`を2回書くというコードの繰り返しが発生していることがわかります:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@ -205,7 +205,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
//// tab | Python 3.9+ 注釈なし
//// tab | Python 3.10+ 注釈なし
/// tip | 豆知識
@ -225,7 +225,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
以下のように書く代わりに:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
@ -233,7 +233,7 @@ commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
////
//// tab | Python 3.9+ 注釈なし
//// tab | Python 3.10+ 注釈なし
/// tip | 豆知識
@ -249,7 +249,7 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
...以下のように書きます:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python
commons: Annotated[CommonQueryParams, Depends()]
@ -257,7 +257,7 @@ commons: Annotated[CommonQueryParams, Depends()]
////
//// tab | Python 3.9+ 注釈なし
//// tab | Python 3.10+ 注釈なし
/// tip | 豆知識

View File

@ -14,7 +14,7 @@
それは`Depends()`の`list`であるべきです:
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *}
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[19] *}
これらの依存関係は、通常の依存関係と同様に実行・解決されます。しかし、それらの値(何かを返す場合)は*path operation 関数*には渡されません。
@ -44,13 +44,13 @@
これらはリクエストの要件(ヘッダーのようなもの)やその他のサブ依存関係を宣言できます:
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *}
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[8,13] *}
### 例外の発生 { #raise-exceptions }
これらの依存関係は、通常の依存関係と同じように例外を`raise`できます:
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *}
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[10,15] *}
### 戻り値 { #return-values }
@ -58,7 +58,7 @@
つまり、すでにどこかで使っている通常の依存関係(値を返すもの)を再利用でき、値は使われなくても依存関係は実行されます:
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *}
{* ../../docs_src/dependencies/tutorial006_an_py310.py hl[11,16] *}
## *path operation*のグループに対する依存関係 { #dependencies-for-a-group-of-path-operations }

View File

@ -1,6 +1,6 @@
# `yield`を持つ依存関係 { #dependencies-with-yield }
FastAPIは、いくつかの<abbr title='sometimes also called "exit code", "cleanup code", "teardown code", "closing code", "context manager exit code", etc. 「exit code」「cleanup code」「teardown code」「closing code」「context manager exit code」などと呼ばれることもあります。'>終了後の追加のステップ</abbr>を行う依存関係をサポートしています。
FastAPIは、いくつかの<dfn title="「終了コード」「クリーンアップコード」「ティアダウンコード」「クローズコード」「コンテキストマネージャの終了コード」などと呼ばれることもあります">終了後の追加のステップ</dfn>を行う依存関係をサポートしています。
これを行うには、`return`の代わりに`yield`を使い、その後に追加のステップ(コード)を書きます。
@ -29,15 +29,15 @@ FastAPIは、いくつかの<abbr title='sometimes also called "exit code", "cle
レスポンスを作成する前に、`yield`文より前のコード(および`yield`文を含む)が実行されます:
{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *}
{* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *}
生成された値は、*path operations*や他の依存関係に注入されるものです:
{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *}
{* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *}
`yield`文に続くコードは、レスポンスの後に実行されます:
{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *}
{* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *}
/// tip | 豆知識
@ -57,7 +57,7 @@ FastAPIは、いくつかの<abbr title='sometimes also called "exit code", "cle
同様に、`finally`を用いて例外があったかどうかにかかわらず、終了ステップを確実に実行することができます。
{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *}
{* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *}
## `yield`を持つサブ依存関係 { #sub-dependencies-with-yield }
@ -67,7 +67,7 @@ FastAPIは、いくつかの<abbr title='sometimes also called "exit code", "cle
例えば、`dependency_c`は`dependency_b`に、そして`dependency_b`は`dependency_a`に依存することができます:
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *}
{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *}
そして、それらはすべて`yield`を使用することができます。
@ -75,7 +75,7 @@ FastAPIは、いくつかの<abbr title='sometimes also called "exit code", "cle
そして、`dependency_b`は`dependency_a`(ここでは`dep_a`という名前)の値を終了コードで利用できるようにする必要があります。
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *}
{* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *}
同様に、`yield`を持つ依存関係と`return`を持つ他の依存関係をいくつか持ち、それらの一部が他の一部に依存するようにもできます。
@ -109,7 +109,7 @@ FastAPIは、いくつかの<abbr title='sometimes also called "exit code", "cle
///
{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *}
{* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *}
例外をキャッチして、それに基づいてカスタムレスポンスを作成したい場合は、[カスタム例外ハンドラ](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}を作成してください。
@ -117,7 +117,7 @@ FastAPIは、いくつかの<abbr title='sometimes also called "exit code", "cle
`yield`を持つ依存関係で`except`を使って例外をキャッチし、それを再度raiseしないまたは新しい例外をraiseしない場合、通常のPythonと同じように、FastAPIは例外があったことに気づけません:
{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *}
{* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *}
この場合、(`HTTPException`やそれに類するものをraiseしていないためクライアントには適切に*HTTP 500 Internal Server Error*レスポンスが返りますが、サーバーには**ログが一切残らず**、何がエラーだったのかを示す他の手がかりもありません。 😱
@ -127,7 +127,7 @@ FastAPIは、いくつかの<abbr title='sometimes also called "exit code", "cle
`raise`を使うと同じ例外を再raiseできます:
{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *}
{* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *}
これでクライアントは同じ*HTTP 500 Internal Server Error*レスポンスを受け取りますが、サーバーのログにはカスタムの`InternalError`が残ります。 😎
@ -190,7 +190,7 @@ participant tasks as Background tasks
しかし、*path operation 関数*からreturnした後に依存関係を使う必要がないと分かっている場合は、`Depends(scope="function")`を使って、**レスポンスが送信される前**に、*path operation 関数*のreturn後に依存関係を閉じるべきだとFastAPIに伝えられます。
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
{* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *}
`Depends()`は、以下のいずれかを取る`scope`パラメータを受け取ります:
@ -268,7 +268,7 @@ Pythonでは、<a href="https://docs.python.org/3/reference/datamodel.html#conte
また、依存関数の中で`with`や`async with`文を使用することによって`yield`を持つ **FastAPI** の依存関係の中でそれらを使用することができます:
{* ../../docs_src/dependencies/tutorial010_py39.py hl[1:9,13] *}
{* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *}
/// tip | 豆知識

View File

@ -0,0 +1,15 @@
# グローバルな依存関係 { #global-dependencies }
アプリケーションの種類によっては、アプリ全体に依存関係を追加したい場合があります。
[`dependencies` を path operation のデコレータに追加](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}できるのと同様に、`FastAPI` アプリケーション自体にも追加できます。
その場合、アプリケーション内のすべての path operation に適用されます:
{* ../../docs_src/dependencies/tutorial012_an_py310.py hl[17] *}
また、[`dependencies` を path operation のデコレータに追加](dependencies-in-path-operation-decorators.md){.internal-link target=_blank}する節で説明した考え方はすべて引き続き当てはまりますが、この場合はアプリ内のすべての path operation に対して適用されます。
## path operation のグループに対する依存関係 { #dependencies-for-groups-of-path-operations }
後で、複数ファイルを含む大規模アプリケーションの構成方法([大規模アプリケーション - 複数ファイル](../../tutorial/bigger-applications.md){.internal-link target=_blank}を読むと、path operation のグループに対して 1 つの `dependencies` パラメータを宣言する方法を学びます。

View File

@ -1,6 +1,6 @@
# 依存関係 { #dependencies }
**FastAPI** は非常に強力でありながら直感的な **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** システムを持っています。
**FastAPI** は非常に強力でありながら直感的な **<dfn title="別名: コンポーネント、リソース、プロバイダ、サービス、インジェクタブル">依存性注入</dfn>** システムを持っています。
それは非常にシンプルに使用できるように設計されており、開発者が他のコンポーネント **FastAPI** と統合するのが非常に簡単になるように設計されています。

View File

@ -58,11 +58,11 @@ query_extractor --> query_or_cookie_extractor --> read_query
依存関係の1つが同じ*path operation*に対して複数回宣言されている場合、例えば、複数の依存関係が共通のサブ依存関係を持っている場合、**FastAPI** はリクエストごとに1回だけそのサブ依存関係を呼び出します。
そして、返された値を<abbr title="A utility/system to store computed/generated values, to reuse them instead of computing them again. 計算/生成された値を保存し、再計算する代わりに再利用するためのユーティリティ/システム">「キャッシュ」</abbr>に保存し、同じリクエストに対して依存関係を何度も呼び出す代わりに、その特定のリクエストでそれを必要とする全ての「依存」に渡すことになります。
そして、返された値を<dfn title="計算/生成された値を保存し、再計算する代わりに再利用するためのユーティリティ/システム">「キャッシュ」</dfn>に保存し、同じリクエストに対して依存関係を何度も呼び出す代わりに、その特定のリクエストでそれを必要とする全ての「依存」に渡すことになります。
高度なシナリオでは、「キャッシュされた」値を使うのではなく、同じリクエストの各ステップ(おそらく複数回)で依存関係を呼び出す必要があることがわかっている場合、`Depends`を使用する際に、`use_cache=False`というパラメータを設定することができます:
//// tab | Python 3.9+
//// tab | Python 3.10+
```Python hl_lines="1"
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
@ -71,7 +71,7 @@ async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_ca
////
//// tab | Python 3.9+ 非Annotated
//// tab | Python 3.10+ 非Annotated
/// tip | 豆知識

View File

@ -1,4 +1,4 @@
# Extra Models { #extra-models }
# 追加のモデル { #extra-models }
先ほどの例に続き、複数の関連モデルを持つことは一般的です。
@ -8,7 +8,7 @@
* **出力モデル**はパスワードをもつべきではありません。
* **データベースモデル**はおそらくハッシュ化されたパスワードが必要になるでしょう。
/// danger
/// danger | 警告
ユーザーの平文のパスワードは絶対に保存しないでください。常に検証できる「安全なハッシュ」を保存してください。
@ -16,13 +16,13 @@
///
## Multiple models { #multiple-models }
## 複数のモデル { #multiple-models }
ここでは、パスワードフィールドをもつモデルがどのように見えるのか、また、どこで使われるのか、大まかなイメージを紹介します:
{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *}
### About `**user_in.model_dump()` { #about-user-in-model-dump }
### `**user_in.model_dump()` について { #about-user-in-model-dump }
#### Pydanticの`.model_dump()` { #pydantics-model-dump }
@ -132,13 +132,13 @@ UserInDB(
)
```
/// warning
/// warning | 注意
追加のサポート関数`fake_password_hasher`と`fake_save_user`は、データの可能な流れをデモするだけであり、もちろん本当のセキュリティを提供しているわけではありません。
///
## Reduce duplication { #reduce-duplication }
## 重複の削減 { #reduce-duplication }
コードの重複を減らすことは、**FastAPI**の中核的なアイデアの1つです。
@ -156,7 +156,7 @@ UserInDB(
{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *}
## `Union` or `anyOf` { #union-or-anyof }
## `Union` または `anyOf` { #union-or-anyof }
レスポンスを2つ以上の型の`Union`として宣言できます。つまり、そのレスポンスはそれらのいずれかになります。
@ -186,25 +186,25 @@ some_variable: PlaneItem | CarItem
しかし、これを代入で`response_model=PlaneItem | CarItem`のように書くと、Pythonはそれを型アテーションとして解釈するのではなく、`PlaneItem`と`CarItem`の間で**無効な操作**を行おうとしてしまうため、エラーになります。
## List of models { #list-of-models }
## モデルのリスト { #list-of-models }
同じように、オブジェクトのリストのレスポンスを宣言できます。
そのためには、標準のPythonの`typing.List`またはPython 3.9以降では単に`list`を使用します:
そのためには、標準のPythonの`list`を使用します:
{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *}
{* ../../docs_src/extra_models/tutorial004_py310.py hl[18] *}
## Response with arbitrary `dict` { #response-with-arbitrary-dict }
## 任意の`dict`によるレスポンス { #response-with-arbitrary-dict }
また、Pydanticモデルを使用せずに、キーと値の型だけを定義した任意の`dict`を使ってレスポンスを宣言することもできます。
これは、有効なフィールド・属性名Pydanticモデルに必要なものを事前に知らない場合に便利です。
この場合、`typing.Dict`またはPython 3.9以降では単に`dict`を使用できます:
この場合、`dict`を使用できます:
{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *}
{* ../../docs_src/extra_models/tutorial005_py310.py hl[6] *}
## Recap { #recap }
## まとめ { #recap }
複数のPydanticモデルを使用し、ケースごとに自由に継承します。

View File

@ -2,7 +2,7 @@
最もシンプルなFastAPIファイルは以下のようになります:
{* ../../docs_src/first_steps/tutorial001_py39.py *}
{* ../../docs_src/first_steps/tutorial001_py310.py *}
これを`main.py`にコピーします。
@ -104,7 +104,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
#### OpenAPIおよびJSONスキーマ { #openapi-and-json-schema }
OpenAPIはAPIのためのAPIスキーマを定義します。そして、そのスキーマは**JSONデータスキーマ**の標準規格に準拠したJSONスキーマを利用するAPIによって送受されるデータの定義または「スキーマ」を含んでいます。
OpenAPIはAPIのためのAPIスキーマを定義します。そして、そのスキーマは**JSONデータスキーマ**の標準規格である**JSON Schema**を利用するAPIによって送受されるデータの定義または「スキーマ」を含んでいます。
#### `openapi.json`を確認 { #check-the-openapi-json }
@ -183,7 +183,7 @@ Deploying to FastAPI Cloud...
### Step 1: `FastAPI`をインポート { #step-1-import-fastapi }
{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *}
{* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *}
`FastAPI`は、APIのすべての機能を提供するPythonクラスです。
@ -197,7 +197,7 @@ Deploying to FastAPI Cloud...
### Step 2: `FastAPI`の「インスタンス」を生成 { #step-2-create-a-fastapi-instance }
{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *}
{* ../../docs_src/first_steps/tutorial001_py310.py hl[3] *}
ここで、`app`変数が`FastAPI`クラスの「インスタンス」になります。
これが、すべてのAPIを作成するための主要なポイントになります。
@ -265,12 +265,12 @@ APIを構築するときは、通常、これらの特定のHTTPメソッドを
#### *path operation デコレータ*を定義 { #define-a-path-operation-decorator }
{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *}
{* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *}
`@app.get("/")`は直下の関数が下記のリクエストの処理を担当することを**FastAPI**に伝えます:
* パス `/`
* <abbr title="an HTTP GET method"><code>get</code> オペレーション</abbr>
* <dfn title="HTTP GET メソッド"><code>get</code> オペレーション</dfn>
/// info | `@decorator` Info
@ -319,7 +319,7 @@ Pythonにおける`@something`シンタックスはデコレータと呼ばれ
* **オペレーション**: は`get`です。
* **関数**: 「デコレータ」の直下にある関数 (`@app.get("/")`の直下) です。
{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *}
{* ../../docs_src/first_steps/tutorial001_py310.py hl[7] *}
これは、Pythonの関数です。
@ -331,7 +331,7 @@ Pythonにおける`@something`シンタックスはデコレータと呼ばれ
`async def`の代わりに通常の関数として定義することもできます:
{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *}
{* ../../docs_src/first_steps/tutorial003_py310.py hl[7] *}
/// note | 備考
@ -341,7 +341,7 @@ Pythonにおける`@something`シンタックスはデコレータと呼ばれ
### Step 5: コンテンツの返信 { #step-5-return-the-content }
{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *}
{* ../../docs_src/first_steps/tutorial001_py310.py hl[8] *}
`dict`、`list`、`str`、`int`などの単一の値を返すことができます。

View File

@ -25,7 +25,7 @@ HTTPレスポンスをエラーでクライアントに返すには、`HTTPExcep
### `HTTPException`のインポート { #import-httpexception }
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *}
{* ../../docs_src/handling_errors/tutorial001_py310.py hl[1] *}
### コード内での`HTTPException`の発生 { #raise-an-httpexception-in-your-code }
@ -39,7 +39,7 @@ Pythonの例外なので、`return`ではなく、`raise`です。
この例では、クライアントが存在しないIDでアイテムを要求した場合、`404`のステータスコードを持つ例外を発生させます:
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *}
{* ../../docs_src/handling_errors/tutorial001_py310.py hl[11] *}
### レスポンス結果 { #the-resulting-response }
@ -77,7 +77,7 @@ Pythonの例外なので、`return`ではなく、`raise`です。
しかし、高度なシナリオのために必要な場合には、カスタムヘッダーを追加することができます:
{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *}
{* ../../docs_src/handling_errors/tutorial002_py310.py hl[14] *}
## カスタム例外ハンドラのインストール { #install-custom-exception-handlers }
@ -89,7 +89,7 @@ Pythonの例外なので、`return`ではなく、`raise`です。
カスタム例外ハンドラを`@app.exception_handler()`で追加することができます:
{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *}
{* ../../docs_src/handling_errors/tutorial003_py310.py hl[5:7,13:18,24] *}
ここで、`/unicorns/yolo`をリクエストすると、*path operation*は`UnicornException`を`raise`します。
@ -127,7 +127,7 @@ Pythonの例外なので、`return`ではなく、`raise`です。
この例外ハンドラは`Request`と例外を受け取ります。
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *}
{* ../../docs_src/handling_errors/tutorial004_py310.py hl[2,14:19] *}
これで、`/items/foo`にアクセスすると、以下のデフォルトのJSONエラーの代わりに:
@ -159,7 +159,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
例えば、これらのエラーに対しては、JSONではなくプレーンテキストを返すようにすることができます:
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *}
{* ../../docs_src/handling_errors/tutorial004_py310.py hl[3:4,9:11,25] *}
/// note | 技術詳細
@ -183,7 +183,7 @@ Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to pa
アプリ開発中にボディのログを取ってデバッグしたり、ユーザーに返したりなどに使用することができます。
{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *}
{* ../../docs_src/handling_errors/tutorial005_py310.py hl[14] *}
ここで、以下のような無効な項目を送信してみてください:
@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
**FastAPI** から同じデフォルトの例外ハンドラと一緒に例外を使用したい場合は、`fastapi.exception_handlers`からデフォルトの例外ハンドラをインポートして再利用できます:
{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *}
{* ../../docs_src/handling_errors/tutorial006_py310.py hl[2:5,15,21] *}
この例では、非常に表現力のあるメッセージでエラーを`print`しているだけですが、要点は理解できるはずです。例外を使用し、その後デフォルトの例外ハンドラを再利用できます。

View File

@ -0,0 +1,72 @@
# ヘッダーパラメータのモデル { #header-parameter-models }
関連する**ヘッダーパラメータ**が一式ある場合、それらを宣言するための**Pydantic モデル**を作成できます。
これにより、モデルを**複数箇所**で**再利用**でき、さらにすべてのパラメータに対するバリデーションやメタデータを一括で宣言できます。😎
/// note | 備考
これは FastAPI バージョン `0.115.0` 以降でサポートされています。🤓
///
## Pydantic モデルによるヘッダーパラメータ { #header-parameters-with-a-pydantic-model }
必要な**ヘッダーパラメータ**を**Pydantic モデル**内で宣言し、関数引数ではそのパラメータを `Header` として宣言します:
{* ../../docs_src/header_param_models/tutorial001_an_py310.py hl[9:14,18] *}
**FastAPI** はリクエストの**ヘッダー**から**各フィールド**の値を**抽出**し、定義した Pydantic モデルとして渡します。
## ドキュメントの確認 { #check-the-docs }
`/docs` のドキュメント UI で必要なヘッダーを確認できます:
<div class="screenshot">
<img src="/img/tutorial/header-param-models/image01.png">
</div>
## 余分なヘッダーを禁止 { #forbid-extra-headers }
特殊なユースケース(あまり一般的ではありません)では、受け付けるヘッダーを**制限**したい場合があります。
Pydantic のモデル設定で `extra` フィールドを `forbid` にして禁止できます:
{* ../../docs_src/header_param_models/tutorial002_an_py310.py hl[10] *}
クライアントが**余分なヘッダー**を送信しようとすると、**エラー**レスポンスが返されます。
例えば、クライアントが値 `plumbus``tool` ヘッダーを送ろうとすると、ヘッダーパラメータ `tool` は許可されていない旨の**エラー**レスポンスが返されます:
```json
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["header", "tool"],
"msg": "Extra inputs are not permitted",
"input": "plumbus",
}
]
}
```
## アンダースコア変換の無効化 { #disable-convert-underscores }
通常のヘッダーパラメータと同様に、パラメータ名にアンダースコアがある場合は**自動的にハイフンに変換**されます。
例えば、コード上でヘッダーパラメータ `save_data` を定義すると、想定される HTTP ヘッダーは `save-data` となり、ドキュメント上にもそのように表示されます。
何らかの理由でこの自動変換を無効化する必要がある場合、ヘッダーパラメータ用の Pydantic モデルでも無効化できます。
{* ../../docs_src/header_param_models/tutorial003_an_py310.py hl[19] *}
/// warning | 注意
`convert_underscores``False` に設定する前に、アンダースコアを含むヘッダーの使用を禁止している HTTP プロキシやサーバーがあることに留意してください。
///
## まとめ { #summary }
**Pydantic モデル**を使って **FastAPI** で **ヘッダー**を宣言できます。😎

View File

@ -18,7 +18,7 @@ OpenAPI仕様および自動APIドキュメントUIで使用される次のフ
以下のように設定できます:
{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *}
{* ../../docs_src/metadata/tutorial001_py310.py hl[3:16, 19:32] *}
/// tip | 豆知識
@ -36,7 +36,7 @@ OpenAPI 3.1.0 および FastAPI 0.99.0 以降では、`license_info` を `url`
例:
{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *}
{* ../../docs_src/metadata/tutorial001_1_py310.py hl[31] *}
## タグのメタデータ { #metadata-for-tags }
@ -58,7 +58,7 @@ OpenAPI 3.1.0 および FastAPI 0.99.0 以降では、`license_info` を `url`
タグのメタデータを作成し、それを `openapi_tags` パラメータに渡します:
{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *}
{* ../../docs_src/metadata/tutorial004_py310.py hl[3:16,18] *}
説明の中でMarkdownを使用できることに注意してください。たとえば「login」は太字 (**login**) で表示され、「fancy」は斜体 (_fancy_) で表示されます。
@ -72,7 +72,7 @@ OpenAPI 3.1.0 および FastAPI 0.99.0 以降では、`license_info` を `url`
*path operation*(および `APIRouter`)の `tags` パラメータを使用して、それらを異なるタグに割り当てます:
{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *}
{* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *}
/// info | 情報
@ -100,7 +100,7 @@ OpenAPI 3.1.0 および FastAPI 0.99.0 以降では、`license_info` を `url`
たとえば、`/api/v1/openapi.json` で提供されるように設定するには:
{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *}
{* ../../docs_src/metadata/tutorial002_py310.py hl[3] *}
OpenAPIスキーマを完全に無効にする場合は、`openapi_url=None` を設定できます。これにより、それを使用するドキュメントUIも無効になります。
@ -117,4 +117,4 @@ OpenAPIスキーマを完全に無効にする場合は、`openapi_url=None` を
たとえば、`/documentation` でSwagger UIが提供されるように設定し、ReDocを無効にするには:
{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *}
{* ../../docs_src/metadata/tutorial003_py310.py hl[3] *}

View File

@ -31,7 +31,7 @@
* 次に、対応する*path operation*によって生成された `response` を返します。
* その後、`response` を返す前にさらに `response` を変更することもできます。
{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}
{* ../../docs_src/middleware/tutorial001_py310.py hl[8:9,11,14] *}
/// tip | 豆知識
@ -57,7 +57,7 @@
例えば、リクエストの処理とレスポンスの生成にかかった秒数を含むカスタムヘッダー `X-Process-Time` を追加できます:
{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *}
{* ../../docs_src/middleware/tutorial001_py310.py hl[10,12:13] *}
/// tip | 豆知識
@ -92,4 +92,4 @@ app.add_middleware(MiddlewareB)
他のミドルウェアの詳細については、[高度なユーザーガイド: 高度なミドルウェア](../advanced/middleware.md){.internal-link target=_blank}を参照してください。
次のセクションでは、ミドルウェアを使用して <abbr title="Cross-Origin Resource Sharing">CORS</abbr> を処理する方法について説明します。
次のセクションでは、ミドルウェアを使用して <abbr title="Cross-Origin Resource Sharing - クロスオリジンリソース共有">CORS</abbr> を処理する方法について説明します。

View File

@ -46,7 +46,7 @@
**FastAPI** は、プレーンな文字列の場合と同じ方法でそれをサポートしています:
{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *}
{* ../../docs_src/path_operation_configuration/tutorial002b_py310.py hl[1,8:10,13,18] *}
## 概要と説明 { #summary-and-description }
@ -56,7 +56,7 @@
## docstringを用いた説明 { #description-from-docstring }
説明文は長くて複数行におよぶ傾向があるので、関数<abbr title="a multi-line string as the first expression inside a function (not assigned to any variable) used for documentation ドキュメントに使用される関数内の最初の式(変数に代入されていない)としての複数行の文字列">docstring</abbr>内に*path operation*の説明文を宣言できます。すると、**FastAPI** は説明文を読み込んでくれます。
説明文は長くて複数行におよぶ傾向があるので、関数<dfn title="関数内の最初の式(どの変数にも代入されない)として記述される、ドキュメント用の複数行の文字列">docstring</dfn>内に*path operation*の説明文を宣言できます。すると、**FastAPI** は説明文を読み込んでくれます。
docstringに<a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a>を記述すれば、正しく解釈されて表示されます。docstringのインデントを考慮して
@ -90,9 +90,9 @@ OpenAPIは*path operation*ごとにレスポンスの説明を必要としてい
## *path operation*を非推奨にする { #deprecate-a-path-operation }
*path operation*を<abbr title="obsolete, recommended not to use it 非推奨、使わない方がよい">deprecated</abbr>としてマークする必要があるが、それを削除しない場合は、`deprecated`パラメータを渡します:
*path operation*を<dfn title="非推奨、使用しないことを推奨">deprecated</dfn>としてマークする必要があるが、それを削除しない場合は、`deprecated`パラメータを渡します:
{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}
{* ../../docs_src/path_operation_configuration/tutorial006_py310.py hl[16] *}
対話的ドキュメントでは非推奨と明記されます:

View File

@ -54,11 +54,11 @@ Pythonは「デフォルト」を持つ値を「デフォルト」を持たな
そのため、以下のように関数を宣言することができます:
{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *}
{* ../../docs_src/path_params_numeric_validations/tutorial002_py310.py hl[7] *}
ただし、`Annotated`を使う場合はこの問題は起きないことを覚えておいてください。`Query()`や`Path()`に関数パラメータのデフォルト値を使わないためです。
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py310.py *}
## 必要に応じてパラメータを並び替えるトリック { #order-the-parameters-as-you-need-tricks }
@ -81,15 +81,15 @@ Pythonは「デフォルト」を持つ値を「デフォルト」を持たな
関数の最初のパラメータとして`*`を渡します。
Pythonはその`*`で何かをすることはありませんが、それ以降のすべてのパラメータがキーワード引数(キーと値のペア)として呼ばれるべきものであると知っているでしょう。それは<abbr title="From: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>としても知られています。たとえデフォルト値がなくても。
Pythonはその`*`で何かをすることはありませんが、それ以降のすべてのパラメータがキーワード引数(キーと値のペア)として呼ばれるべきものであると知っているでしょう。それは<abbr title="From: K-ey W-ord Arg-uments - キーワード引数"><code>kwargs</code></abbr>としても知られています。たとえデフォルト値がなくても。
{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *}
{* ../../docs_src/path_params_numeric_validations/tutorial003_py310.py hl[7] *}
### `Annotated`のほうがよい { #better-with-annotated }
`Annotated`を使う場合は、関数パラメータのデフォルト値を使わないため、この問題は起きず、おそらく`*`を使う必要もありません。
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py310.py hl[10] *}
## 数値の検証: 以上 { #number-validations-greater-than-or-equal }
@ -97,7 +97,7 @@ Pythonはその`*`で何かをすることはありませんが、それ以降
ここで、`ge=1`の場合、`item_id`は`1`「より大きい`g`か、同じ`e`」整数でなければなりません。
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py310.py hl[10] *}
## 数値の検証: より大きいと小なりイコール { #number-validations-greater-than-and-less-than-or-equal }
@ -106,7 +106,7 @@ Pythonはその`*`で何かをすることはありませんが、それ以降
* `gt`: `g`reater `t`han
* `le`: `l`ess than or `e`qual
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *}
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py310.py hl[10] *}
## 数値の検証: 浮動小数点、 大なり小なり { #number-validations-floats-greater-than-and-less-than }
@ -118,7 +118,7 @@ Pythonはその`*`で何かをすることはありませんが、それ以降
これは<abbr title="less than より小さい"><code>lt</code></abbr>も同じです。
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py310.py hl[13] *}
## まとめ { #recap }

View File

@ -2,7 +2,7 @@
Pythonのformat文字列と同様のシンタックスで「パスパラメータ」や「パス変数」を宣言できます:
{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *}
{* ../../docs_src/path_params/tutorial001_py310.py hl[6:7] *}
パスパラメータ `item_id` の値は、引数 `item_id` として関数に渡されます。
@ -16,7 +16,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
標準のPythonの型アテーションを使用して、関数内のパスパラメータの型を宣言できます:
{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *}
{* ../../docs_src/path_params/tutorial002_py310.py hl[7] *}
ここでは、 `item_id``int` として宣言されています。
@ -26,7 +26,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
///
## データ<abbr title="別名: serialization, parsing, marshalling">変換</abbr> { #data-conversion }
## データ<dfn title="別名: シリアライズ、パース、マーシャリング">変換</dfn> { #data-conversion }
この例を実行し、ブラウザで <a href="http://127.0.0.1:8000/items/3" class="external-link" target="_blank">http://127.0.0.1:8000/items/3</a> を開くと、次のレスポンスが表示されます:
@ -38,7 +38,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
関数が受け取った(および返した)値は、文字列の `"3"` ではなく、Pythonの `int` としての `3` であることに注意してください。
したがって、その型宣言を使うと、**FastAPI**は自動リクエスト <abbr title="HTTPリクエストで受け取った文字列をPythonデータへ変換する">"解析"</abbr> を行います。
したがって、その型宣言を使うと、**FastAPI**は自動リクエスト <dfn title="HTTPリクエストから受け取った文字列をPythonのデータに変換する">"解析"</dfn> を行います。
///
@ -118,13 +118,13 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
*path operations* は順に評価されるので、 `/users/me``/users/{user_id}` よりも先に宣言されているか確認する必要があります:
{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *}
{* ../../docs_src/path_params/tutorial003_py310.py hl[6,11] *}
それ以外の場合、 `/users/{user_id}``/users/me` としてもマッチします。値が `"me"` であるパラメータ `user_id` を受け取ると「考え」ます。
同様に、path operation を再定義することはできません:
{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *}
{* ../../docs_src/path_params/tutorial003b_py310.py hl[6,11] *}
パスは最初にマッチしたものが常に使われるため、最初のものが常に使用されます。
@ -140,11 +140,11 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
そして、固定値のクラス属性を作ります。すると、その値が使用可能な値となります:
{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
{* ../../docs_src/path_params/tutorial005_py310.py hl[1,6:9] *}
/// tip | 豆知識
"AlexNet"、"ResNet"そして"LeNet"は機械学習<abbr title="Technically, Deep Learning model architectures">モデル</abbr>の名前です。
"AlexNet"、"ResNet"そして"LeNet"は機械学習<dfn title="厳密には、Deep Learning のモデルアーキテクチャ">モデル</dfn>の名前です。
///
@ -152,7 +152,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
次に、作成したenumクラスである`ModelName`を使用した型アノテーションをもつ*パスパラメータ*を作成します:
{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *}
{* ../../docs_src/path_params/tutorial005_py310.py hl[16] *}
### ドキュメントの確認 { #check-the-docs }
@ -168,13 +168,13 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
これは、作成した列挙型 `ModelName` の*列挙型メンバ*と比較できます:
{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *}
{* ../../docs_src/path_params/tutorial005_py310.py hl[17] *}
#### *列挙値*の取得 { #get-the-enumeration-value }
`model_name.value` 、もしくは一般に、 `your_enum_member.value` を使用して実際の値 (この場合は `str`) を取得できます。
{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *}
{* ../../docs_src/path_params/tutorial005_py310.py hl[20] *}
/// tip | 豆知識
@ -188,7 +188,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
それらはクライアントに返される前に適切な値 (この場合は文字列) に変換されます。
{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
{* ../../docs_src/path_params/tutorial005_py310.py hl[18,21,23] *}
クライアントは以下の様なJSONレスポンスを得ます:
@ -227,7 +227,7 @@ Starletteのオプションを直接使用することで、以下のURLの様
したがって、以下の様に使用できます:
{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
{* ../../docs_src/path_params/tutorial004_py310.py hl[6] *}
/// tip | 豆知識
@ -242,7 +242,7 @@ Starletteのオプションを直接使用することで、以下のURLの様
簡潔で、本質的で、標準的なPythonの型宣言を使用することで、**FastAPI**は以下を行います:
* エディターサポート: エラーチェック、自動補完、など
* データ「<abbr title="HTTPリクエストで受け取った文字列をPythonデータへ変換する">解析</abbr>
* データ「<dfn title="HTTPリクエストから受け取った文字列をPythonのデータに変換する">解析</dfn>
* データバリデーション
* APIアテーションと自動ドキュメント生成

View File

@ -47,40 +47,16 @@ FastAPI はバージョン 0.95.0 で `Annotated` のサポートを追加し(
次の型アノテーションがありました:
//// tab | Python 3.10+
```Python
q: str | None = None
```
////
//// tab | Python 3.9+
```Python
q: Union[str, None] = None
```
////
これを `Annotated` で包んで、次のようにします:
//// tab | Python 3.10+
```Python
q: Annotated[str | None] = None
```
////
//// tab | Python 3.9+
```Python
q: Annotated[Union[str, None]] = None
```
////
どちらも同じ意味で、`q` は `str` または `None` になり得るパラメータで、デフォルトでは `None` です。
では、面白いところに進みましょう。 🎉
@ -109,7 +85,7 @@ FastAPI は次を行います:
## 代替(古い方法): デフォルト値としての `Query` { #alternative-old-query-as-the-default-value }
FastAPI の以前のバージョン(<abbr title="before 2023-03">0.95.0</abbr> より前)では、パラメータのデフォルト値として `Query` を使う必要があり、`Annotated` の中に入れるのではありませんでした。これを使ったコードを見かける可能性が高いので、説明します。
FastAPI の以前のバージョン(<dfn title="2023-03 より前">0.95.0</dfn> より前)では、パラメータのデフォルト値として `Query` を使う必要があり、`Annotated` の中に入れるのではありませんでした。これを使ったコードを見かける可能性が高いので、説明します。
/// tip | 豆知識
@ -192,7 +168,7 @@ FastAPI なしで同じ関数を **別の場所** から **呼び出しても**
## 正規表現の追加 { #add-regular-expressions }
パラメータが一致するべき <abbr title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings.">正規表現</abbr> `pattern` を定義することができます:
パラメータが一致するべき <dfn title="正規表現、regex、regexp は、文字列に対する検索パターンを定義する文字の並びです。">正規表現</dfn> `pattern` を定義することができます:
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
@ -212,7 +188,7 @@ FastAPI なしで同じ関数を **別の場所** から **呼び出しても**
クエリパラメータ `q``min_length``3` とし、デフォルト値を `"fixedquery"` として宣言したいとします:
{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial005_an_py310.py hl[9] *}
/// note | 備考
@ -242,7 +218,7 @@ q: Annotated[str | None, Query(min_length=3)] = None
そのため、`Query` を使いながら値を必須として宣言したい場合は、単にデフォルト値を宣言しません:
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial006_an_py310.py hl[9] *}
### 必須、`None` にできる { #required-can-be-none }
@ -293,7 +269,7 @@ http://localhost:8000/items/?q=foo&q=bar
また、値が指定されていない場合はデフォルトの `list` を定義することもできます。
{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *}
以下にアクセスすると:
@ -316,7 +292,7 @@ http://localhost:8000/items/
`list[str]` の代わりに直接 `list` を使うこともできます:
{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
{* ../../docs_src/query_params_str_validations/tutorial013_an_py310.py hl[9] *}
/// note | 備考
@ -372,7 +348,7 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
さて、このパラメータが気に入らなくなったとしましょう。
それを使っているクライアントがいるので、しばらくは残しておく必要がありますが、ドキュメントには<abbr title="obsolete, recommended not to use it">deprecated</abbr>と明記しておきたいです。
それを使っているクライアントがいるので、しばらくは残しておく必要がありますが、ドキュメントには<abbr title="obsolete, recommended not to use it - 廃止予定、使用は推奨されません">deprecated</abbr>と明記しておきたいです。
その場合、`Query`にパラメータ`deprecated=True`を渡します:
@ -402,7 +378,7 @@ Pydantic には <a href="https://docs.pydantic.dev/latest/concepts/validators/#f
///
例えば、このカスタムバリデータは、<abbr title="ISBN means International Standard Book Number 国際標準図書番号">ISBN</abbr> の書籍番号なら item ID が `isbn-` で始まること、<abbr title="IMDB (Internet Movie Database) is a website with information about movies IMDBInternet Movie Databaseは映画に関する情報を掲載するWebサイトです">IMDB</abbr> の movie URL ID なら `imdb-` で始まることをチェックします:
例えば、このカスタムバリデータは、<abbr title="International Standard Book Number - 国際標準図書番号">ISBN</abbr> の書籍番号なら item ID が `isbn-` で始まること、<abbr title="Internet Movie Database - インターネット・ムービー・データベース: 映画に関する情報を掲載する Web サイト">IMDB</abbr> の movie URL ID なら `imdb-` で始まることをチェックします:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
@ -436,7 +412,7 @@ Pydantic には <a href="https://docs.pydantic.dev/latest/concepts/validators/#f
#### ランダムなアイテム { #a-random-item }
`data.items()` で、辞書の各アイテムのキーと値を含むタプルを持つ <abbr title="Something we can iterate on with a for loop, like a list, set, etc.">反復可能オブジェクト</abbr> を取得します。
`data.items()` で、辞書の各アイテムのキーと値を含むタプルを持つ <dfn title="for ループで繰り返し処理できるものlist、set など)">反復可能オブジェクト</dfn> を取得します。
この反復可能オブジェクトを `list(data.items())` で適切な `list` に変換します。

View File

@ -2,7 +2,7 @@
パスパラメータではない関数パラメータを宣言すると、それらは自動的に「クエリ」パラメータとして解釈されます。
{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *}
{* ../../docs_src/query_params/tutorial001_py310.py hl[9] *}
クエリはURL内で `?` の後に続くキーとバリューの組で、 `&` で区切られています。
@ -24,7 +24,7 @@ http://127.0.0.1:8000/items/?skip=0&limit=10
パスパラメータに適用される処理と完全に同様な処理がクエリパラメータにも施されます:
* エディターサポート (明らかに)
* データ <abbr title="converting the string that comes from an HTTP request into Python data">「解析」</abbr>
* データ <dfn title="HTTP リクエストから来る文字列を Python のデータに変換すること">「解析」</dfn>
* データバリデーション
* 自動ドキュメント生成
@ -128,7 +128,7 @@ http://127.0.0.1:8000/items/foo?short=yes
しかしクエリパラメータを必須にしたい場合は、ただデフォルト値を宣言しなければよいです:
{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *}
{* ../../docs_src/query_params/tutorial005_py310.py hl[6:7] *}
ここで、クエリパラメータ `needy``str` 型の必須のクエリパラメータです。

View File

@ -0,0 +1,176 @@
# リクエストファイル { #request-files }
`File` を使って、クライアントがアップロードするファイルを定義できます。
/// info | 情報
アップロードされたファイルを受け取るには、まず <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a> をインストールします。
[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成して有効化し、次のようにインストールしてください:
```console
$ pip install python-multipart
```
アップロードされたファイルは「form data」として送信されるためです。
///
## `File` をインポート { #import-file }
`fastapi` から `File``UploadFile` をインポートします:
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[3] *}
## `File` パラメータの定義 { #define-file-parameters }
`Body``Form` と同様の方法でファイルのパラメータを作成します:
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[9] *}
/// info | 情報
`File``Form` を直接継承したクラスです。
ただし、`fastapi` から `Query`、`Path`、`File` などをインポートするとき、それらは実際には特殊なクラスを返す関数であることに注意してください。
///
/// tip | 豆知識
ファイルのボディを宣言するには `File` を使う必要があります。そうしないと、パラメータはクエリパラメータやボディJSONパラメータとして解釈されます。
///
ファイルは「form data」としてアップロードされます。
*path operation 関数* のパラメータの型を `bytes` として宣言すると、**FastAPI** がファイルを読み取り、内容を `bytes` として受け取ります。
これは内容全体がメモリに保持されることを意味します。小さなファイルには有効です。
しかし、多くの場合は `UploadFile` を使う方が有利です。
## `UploadFile` によるファイルパラメータ { #file-parameters-with-uploadfile }
型を `UploadFile` にしてファイルパラメータを定義します:
{* ../../docs_src/request_files/tutorial001_an_py310.py hl[14] *}
`UploadFile` を使うことには `bytes` に対する次の利点があります:
- パラメータのデフォルト値に `File()` を使う必要がありません。
- 「spooled」ファイルを使います:
- 最大サイズまではメモリに保持し、それを超えるとディスクに格納されるファイルです。
- そのため、画像・動画・大きなバイナリなどの大きなファイルでも、メモリを使い果たすことなくうまく動作します。
- アップロードされたファイルからメタデータを取得できます。
- <a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a>`async` インターフェースを持ちます。
- 実際の Python の <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a> オブジェクトを公開しており、file-like オブジェクトを期待する他のライブラリにそのまま渡せます。
### `UploadFile` { #uploadfile }
`UploadFile` には次の属性があります:
- `filename`: アップロード時の元のファイル名を表す `str`(例: `myimage.jpg`
- `content_type`: コンテントタイプMIME タイプ / メディアタイプ)を表す `str`(例: `image/jpeg`
- `file`: <a href="https://docs.python.org/3/library/tempfile.html#tempfile.SpooledTemporaryFile" class="external-link" target="_blank">`SpooledTemporaryFile`</a><a href="https://docs.python.org/3/glossary.html#term-file-like-object" class="external-link" target="_blank">file-like</a> なオブジェクト)。これは実際の Python のファイルオブジェクトで、「file-like」オブジェクトを期待する関数やライブラリに直接渡せます。
`UploadFile` には次の `async` メソッドがあります。いずれも内部で対応するファイルメソッド(内部の `SpooledTemporaryFile`)を呼び出します。
- `write(data)`: `data``str` または `bytes`)を書き込みます。
- `read(size)`: `size``int`)バイト/文字を読み込みます。
- `seek(offset)`: ファイル内のバイト位置 `offset``int`)に移動します。
- 例: `await myfile.seek(0)` はファイルの先頭に移動します。
- 一度 `await myfile.read()` を実行して、もう一度内容を読みたい場合に特に便利です。
- `close()`: ファイルを閉じます。
これらはすべて `async` メソッドなので、`await` する必要があります。
例えば、`async` の *path operation 関数* 内では次のように内容を取得できます:
```Python
contents = await myfile.read()
```
通常の `def`*path operation 関数* 内にいる場合は、`UploadFile.file` に直接アクセスできます。例えば:
```Python
contents = myfile.file.read()
```
/// note | `async` の技術詳細
`async` メソッドを使うと、**FastAPI** はファイルメソッドをスレッドプールで実行し、その完了を待機します。
///
/// note | Starlette の技術詳細
**FastAPI** の `UploadFile`**Starlette**`UploadFile` を直接継承していますが、**Pydantic** や FastAPI の他の部分と互換にするために必要な要素を追加しています。
///
## 「Form Data」とは { #what-is-form-data }
HTML フォーム(`<form></form>`がサーバーにデータを送る方法は、そのデータに対して通常「特別な」エンコーディングを用い、JSON とは異なります。
**FastAPI** は JSON ではなく、適切な場所からそのデータを読み取るようにします。
/// note | 技術詳細
ファイルを含まない場合、フォームからのデータは通常「メディアタイプ」`application/x-www-form-urlencoded` でエンコードされます。
ただしフォームにファイルが含まれる場合は、`multipart/form-data` としてエンコードされます。`File` を使うと、**FastAPI** はボディ内の正しい部分からファイルを取得すべきであると認識します。
これらのエンコーディングやフォームフィールドの詳細は、<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network - Mozilla 開発者ネットワーク">MDN</abbr> Web Docs の <code>POST</code></a> を参照してください。
///
/// warning | 注意
1 つの *path operation* に複数の `File` および `Form` パラメータを宣言できますが、同時に JSON として受け取ることを期待する `Body` フィールドを宣言することはできません。リクエストのボディは `application/json` ではなく `multipart/form-data` でエンコードされるためです。
これは **FastAPI** の制限ではなく、HTTP プロトコルの仕様です。
///
## 任意のファイルアップロード { #optional-file-upload }
標準の型アノテーションを使い、デフォルト値を `None` に設定することで、ファイルを任意にできます:
{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}
## 追加メタデータつきの `UploadFile` { #uploadfile-with-additional-metadata }
例えば追加のメタデータを設定するために、`UploadFile` と併せて `File()` を使うこともできます:
{* ../../docs_src/request_files/tutorial001_03_an_py310.py hl[9,15] *}
## 複数ファイルのアップロード { #multiple-file-uploads }
同時に複数のファイルをアップロードできます。
それらは「form data」で送信される同じ「フォームフィールド」に関連付けられます。
そのためには、`bytes` または `UploadFile` のリストを宣言します:
{* ../../docs_src/request_files/tutorial002_an_py310.py hl[10,15] *}
宣言どおり、`bytes` または `UploadFile``list` を受け取ります。
/// note | 技術詳細
`from starlette.responses import HTMLResponse` を使うこともできます。
**FastAPI** は利便性のため、`starlette.responses` と同じものを `fastapi.responses` として提供しています。ただし、利用可能なレスポンスの多くは Starlette から直接提供されています。
///
### 追加メタデータつきの複数ファイルアップロード { #multiple-file-uploads-with-additional-metadata }
先ほどと同様に、`UploadFile` に対しても `File()` を使って追加のパラメータを設定できます:
{* ../../docs_src/request_files/tutorial003_an_py310.py hl[11,18:20] *}
## まとめ { #recap }
リクエストでフォームデータとして送信されるアップロードファイルを宣言するには、`File`、`bytes`、`UploadFile` を使います。

View File

@ -0,0 +1,78 @@
# フォームモデル { #form-models }
FastAPI では、フォームフィールドを宣言するために Pydantic モデルを使用できます。
/// info | 情報
フォームを使うには、まず <a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a> をインストールします。
まず [仮想環境](../virtual-environments.md){.internal-link target=_blank} を作成して有効化し、そのうえでインストールしてください。例えば:
```console
$ pip install python-multipart
```
///
/// note | 備考
これは FastAPI バージョン `0.113.0` 以降でサポートされています。🤓
///
## フォーム用の Pydantic モデル { #pydantic-models-for-forms }
受け取りたいフィールドを **フォームフィールド** として持つ **Pydantic モデル** を宣言し、パラメータを `Form` として宣言するだけです:
{* ../../docs_src/request_form_models/tutorial001_an_py310.py hl[9:11,15] *}
**FastAPI** はリクエストの **フォームデータ** から **各フィールド** のデータを **抽出** し、定義した Pydantic モデルとして渡します。
## ドキュメントで確認 { #check-the-docs }
`/docs` のドキュメント UI で確認できます:
<div class="screenshot">
<img src="/img/tutorial/request-form-models/image01.png">
</div>
## 追加のフォームフィールドを禁止 { #forbid-extra-form-fields }
一部の特殊なユースケース(おそらくあまり一般的ではありません)では、フォームフィールドを Pydantic モデルで宣言したもののみに**制限**し、**追加**のフィールドを**禁止**したい場合があります。
/// note | 備考
これは FastAPI バージョン `0.114.0` 以降でサポートされています。🤓
///
Pydantic のモデル設定で、`extra` フィールドを `forbid` にできます:
{* ../../docs_src/request_form_models/tutorial002_an_py310.py hl[12] *}
クライアントが余分なデータを送信しようとすると、**エラー**のレスポンスを受け取ります。
例えば、クライアントが次のフォームフィールドを送ろうとした場合:
- `username`: `Rick`
- `password`: `Portal Gun`
- `extra`: `Mr. Poopybutthole`
フィールド `extra` は許可されていない旨のエラーレスポンスが返されます:
```json
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["body", "extra"],
"msg": "Extra inputs are not permitted",
"input": "Mr. Poopybutthole"
}
]
}
```
## まとめ { #summary }
FastAPI でフォームフィールドを宣言するために Pydantic モデルを使用できます。😎

View File

@ -16,13 +16,13 @@ $ pip install python-multipart
## `File`と`Form`のインポート { #import-file-and-form }
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *}
{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[3] *}
## `File`と`Form`のパラメータの定義 { #define-file-and-form-parameters }
ファイルやフォームのパラメータは`Body`や`Query`の場合と同じように作成します:
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *}
{* ../../docs_src/request_forms_and_files/tutorial001_an_py310.py hl[10:12] *}
ファイルとフォームフィールドがフォームデータとしてアップロードされ、ファイルとフォームフィールドを受け取ります。

View File

@ -18,17 +18,17 @@ $ pip install python-multipart
`fastapi`から`Form`をインポートします:
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[3] *}
## `Form`のパラメータの定義 { #define-form-parameters }
`Body`や`Query`の場合と同じようにフォームパラメータを作成します:
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *}
{* ../../docs_src/request_forms/tutorial001_an_py310.py hl[9] *}
例えば、OAuth2仕様が使用できる方法の「パスワードフロー」と呼ばれるでは、フォームフィールドとして`username`と`password`を送信する必要があります。
<abbr title="specification 仕様">spec</abbr>では、フィールドの名前が`username`と`password`であることと、JSONではなくフォームフィールドとして送信されることを要求しています。
<dfn title="仕様">仕様</dfn>では、フィールドの名前が正確に`username`と`password`であることと、JSONではなくフォームフィールドとして送信されることを要求しています。
`Form`では`Body`(および`Query`や`Path`、`Cookie`)と同じ設定を宣言することができます。これには、バリデーション、例、エイリアス(例えば`username`の代わりに`user-name`)などが含まれます。
@ -56,13 +56,13 @@ HTMLフォーム`<form></form>`)がサーバにデータを送信する方
しかし、フォームがファイルを含む場合は、`multipart/form-data`としてエンコードされます。ファイルの扱いについては次の章で説明します。
これらのエンコーディングやフォームフィールドの詳細については、<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr><code>POST</code></a>のウェブドキュメントを参照してください。
これらのエンコーディングやフォームフィールドの詳細については、<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST" class="external-link" target="_blank"><abbr title="Mozilla Developer Network - Mozilla 開発者ネットワーク">MDN</abbr><code>POST</code></a>のウェブドキュメントを参照してください。
///
/// warning | 注意
*path operation*で複数の`Form`パラメータを宣言することができますが、JSONとして受け取ることを期待している`Body`フィールドを宣言することはできません。なぜなら、リクエストは`application/json`の代わりに`application/x-www-form-urlencoded`を使ってボディをエンコードするからです。
*path operation*で複数の`Form`パラメータを宣言することができますが、JSONとして受け取ることを期待している`Body`フィールドを宣言することはできません。なぜなら、リクエストは`application/x-www-form-urlencoded`の代わりに`application/json`を使ってボディをエンコードするからです。
これは **FastAPI**の制限ではなく、HTTPプロトコルの一部です。

View File

@ -41,7 +41,7 @@ FastAPIはこの戻り値の型を使って以下を行います:
/// note | 備考
`response_model`は「デコレータ」メソッド(`get`、`post`など)のパラメータであることに注意してください。すべてのパラメータやボディのように、*path operation 関数* のパラメータではありません。
`response_model`は「デコレータ」メソッド(`get`、`post`など)のパラメータです。関数のパラメータやボディなどとは違い、*path operation 関数*のパラメータではありません。
///
@ -183,7 +183,7 @@ Pydanticフィールドとして有効ではないものを返し、ツール
最も一般的なケースは、[高度なドキュメントで後述する「Responseを直接返す」](../advanced/response-directly.md){.internal-link target=_blank}場合です。
{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *}
{* ../../docs_src/response_model/tutorial003_02_py310.py hl[8,10:11] *}
このシンプルなケースは、戻り値の型アノテーションが `Response` のクラスまたはサブクラスであるため、FastAPIが自動的に処理します。
@ -193,7 +193,7 @@ Pydanticフィールドとして有効ではないものを返し、ツール
型アノテーションで `Response` のサブクラスを使うこともできます:
{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *}
{* ../../docs_src/response_model/tutorial003_03_py310.py hl[8:9] *}
これは `RedirectResponse``Response` のサブクラスであり、FastAPIがこのシンプルなケースを自動処理するため、同様に動作します。
@ -201,7 +201,7 @@ Pydanticフィールドとして有効ではないものを返し、ツール
しかし、Pydantic型として有効ではない別の任意のオブジェクト例: データベースオブジェクトを返し、関数でそのようにアテーションすると、FastAPIはその型アテーションからPydanticレスポンスモデルを作成しようとして失敗します。
同様に、<abbr title='複数の型のunionは「これらの型のいずれか」を意味します。'>union</abbr>のように、複数の型のうち1つ以上がPydantic型として有効でないものを含む場合も起こります。例えば次は失敗します 💥:
同様に、<dfn title="複数の型のユニオンは「これらの型のいずれか」を意味します。">ユニオン</dfn>のように、複数の型のうち1つ以上がPydantic型として有効でないものを含む場合も起こります。例えば次は失敗します 💥:
{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *}

View File

@ -8,7 +8,7 @@
* `@app.delete()`
* etc.
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *}
/// note | 備考
@ -74,7 +74,7 @@ HTTPでは、レスポンスの一部として3桁の数字のステータスコ
先ほどの例をもう一度見てみましょう:
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
{* ../../docs_src/response_status_code/tutorial001_py310.py hl[6] *}
`201`は「作成完了」のためのステータスコードです。
@ -82,7 +82,7 @@ HTTPでは、レスポンスの一部として3桁の数字のステータスコ
`fastapi.status`の便利な変数を利用することができます。
{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *}
{* ../../docs_src/response_status_code/tutorial002_py310.py hl[1,6] *}
それらは単なる便利なものであり、同じ番号を保持しています。しかし、その方法ではエディタの自動補完を使用してそれらを見つけることができます。

View File

@ -74,7 +74,7 @@ Pydanticモデルで`Field()`を使う場合、追加の`examples`も宣言で
この場合、examplesはそのボディデータの内部**JSON Schema**の一部になります。
それでも、<abbr title="2023-08-26">執筆時点</abbr>では、ドキュメントUIの表示を担当するツールであるSwagger UIは、**JSON Schema**内のデータに対して複数の例を表示することをサポートしていません。しかし、回避策については以下を読んでください。
それでも、<dfn title="2023-08-26">執筆時点</dfn>では、ドキュメントUIの表示を担当するツールであるSwagger UIは、**JSON Schema**内のデータに対して複数の例を表示することをサポートしていません。しかし、回避策については以下を読んでください。
### OpenAPI固有の`examples` { #openapi-specific-examples }

View File

@ -20,7 +20,7 @@
`main.py`に、下記の例をコピーします:
{* ../../docs_src/security/tutorial001_an_py39.py *}
{* ../../docs_src/security/tutorial001_an_py310.py *}
## 実行 { #run-it }
@ -132,7 +132,7 @@ OAuth2は、バックエンドやAPIがユーザーを認証するサーバー
`OAuth2PasswordBearer` クラスのインスタンスを作成する時に、パラメーター`tokenUrl`を渡します。このパラメーターには、クライアント (ユーザーのブラウザで動作するフロントエンド) がトークンを取得するために`username`と`password`を送信するURLを指定します。
{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *}
{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *}
/// tip | 豆知識
@ -150,7 +150,7 @@ OAuth2は、バックエンドやAPIがユーザーを認証するサーバー
/// info | 情報
非常に厳格な「Pythonista」であれば、パラメーター名のスタイルが`token_url`ではなく`tokenUrl`であることを気に入らないかもしれません。
非常に厳格な「Pythonista」であれば、パラメーター名のスタイルが`tokenUrl`ではなく`token_url`であることを気に入らないかもしれません。
それはOpenAPI仕様と同じ名前を使用しているからです。そのため、これらのセキュリティスキームについてもっと調べる必要がある場合は、それをコピーして貼り付ければ、それについての詳細な情報を見つけることができます。
@ -170,7 +170,7 @@ oauth2_scheme(some, parameters)
これで`oauth2_scheme`を`Depends`で依存関係に渡すことができます。
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}
この依存関係は、*path operation 関数*のパラメーター`token`に代入される`str`を提供します。

View File

@ -2,7 +2,7 @@
一つ前の章では、(依存性注入システムに基づいた)セキュリティシステムは、 *path operation 関数*`str` として `token` を与えていました:
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *}
しかし、それはまだそんなに有用ではありません。

View File

@ -1,4 +1,4 @@
# セキュリティ入門
# セキュリティ入門 { #security }
セキュリティ、認証、認可を扱うには多くの方法があります。
@ -10,11 +10,11 @@
しかし、その前に、いくつかの小さな概念を確認しましょう。
## お急ぎですか?
## お急ぎですか? { #in-a-hurry }
もし、これらの用語に興味がなく、ユーザー名とパスワードに基づく認証でセキュリティを**今すぐ**確保する必要がある場合は、次の章に進んでください。
## OAuth2
## OAuth2 { #oauth2 }
OAuth2は、認証と認可を処理するためのいくつかの方法を定義した仕様です。
@ -24,7 +24,7 @@ OAuth2は、認証と認可を処理するためのいくつかの方法を定
これが、「Facebook、Google、X (Twitter)、GitHubを使ってログイン」を使用したすべてのシステムの背後で使われている仕組みです。
### OAuth 1
### OAuth 1 { #oauth-1 }
OAuth 1というものもありましたが、これはOAuth2とは全く異なり、通信をどのように暗号化するかという仕様が直接的に含まれており、より複雑なものとなっています。
@ -38,7 +38,7 @@ OAuth2は、通信を暗号化する方法を指定せず、アプリケーシ
///
## OpenID Connect
## OpenID Connect { #openid-connect }
OpenID Connectは、**OAuth2**をベースにした別の仕様です。
@ -48,7 +48,7 @@ OpenID Connectは、**OAuth2**をベースにした別の仕様です。
しかし、FacebookのログインはOpenID Connectをサポートしていません。OAuth2を独自にアレンジしています。
### OpenID (「OpenID Connect」ではない)
### OpenID (「OpenID Connect」ではない) { #openid-not-openid-connect }
また、「OpenID」という仕様もありました。それは、**OpenID Connect**と同じことを解決しようとしたものですが、OAuth2に基づいているわけではありませんでした。
@ -56,7 +56,7 @@ OpenID Connectは、**OAuth2**をベースにした別の仕様です。
現在ではあまり普及していませんし、使われてもいません。
## OpenAPI
## OpenAPI { #openapi }
OpenAPI以前はSwaggerとして知られていましたは、APIを構築するためのオープンな仕様です現在はLinux Foundationの一部になっています
@ -97,7 +97,7 @@ Google、Facebook、X (Twitter)、GitHubなど、他の認証/認可プロバイ
///
## **FastAPI** ユーティリティ
## **FastAPI** ユーティリティ { #fastapi-utilities }
FastAPIは `fastapi.security` モジュールの中で、これらのセキュリティスキームごとにいくつかのツールを提供し、これらのセキュリティメカニズムを簡単に使用できるようにします。

View File

@ -1,6 +1,6 @@
# パスワードおよびハッシュ化によるOAuth2、JWTトークンによるBearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens }
これでセキュリティの流れが全てわかったので、<abbr title="JSON Web Tokens">JWT</abbr>トークンと安全なパスワードのハッシュ化を使用して、実際にアプリケーションを安全にしてみましょう。
これでセキュリティの流れが全てわかったので、<abbr title="JSON Web Tokens - JSON Web Token">JWT</abbr>トークンと安全なパスワードのハッシュ化を使用して、実際にアプリケーションを安全にしてみましょう。
このコードは、アプリケーションで実際に使用したり、パスワードハッシュをデータベースに保存するといった用途に利用できます。
@ -116,7 +116,11 @@ pwdlibはbcryptハッシュアルゴリズムもサポートしていますが
さらに、ユーザーを認証して返す関数も作成します。
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *}
`authenticate_user` がデータベースに存在しないユーザー名で呼び出された場合でも、ダミーのハッシュを使って `verify_password` を実行します。
これにより、ユーザー名が有効かどうかに関わらずエンドポイントの応答時間がおおよそ同じになり、既存のユーザー名を列挙するために悪用されうる「タイミング攻撃」を防止できます。
/// note | 備考
@ -152,7 +156,7 @@ JWTトークンの署名に使用するアルゴリズム`"HS256"`を指定し
新しいアクセストークンを生成するユーティリティ関数を作成します。
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *}
## 依存関係の更新 { #update-the-dependencies }
@ -162,7 +166,7 @@ JWTトークンの署名に使用するアルゴリズム`"HS256"`を指定し
トークンが無効な場合は、すぐにHTTPエラーを返します。
{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *}
## `/token` *path operation* の更新 { #update-the-token-path-operation }
@ -170,7 +174,7 @@ JWTトークンの署名に使用するアルゴリズム`"HS256"`を指定し
実際のJWTアクセストークンを作成し、それを返します。
{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}
{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *}
### JWTの「subject」`sub` についての技術的な詳細 { #technical-details-about-the-jwt-subject-sub }

View File

@ -0,0 +1,289 @@
# パスワードとBearerによるシンプルなOAuth2 { #simple-oauth2-with-password-and-bearer }
前章から発展させて、完全なセキュリティフローに必要な不足部分を追加していきます。
## `username``password` を取得する { #get-the-username-and-password }
`username``password` を取得するために **FastAPI** のセキュリティユーティリティを使います。
OAuth2 では、「password flow」ここで使用するフローを使う場合、クライアント/ユーザーはフォームデータとして `username``password` フィールドを送信する必要があります。
しかも、フィールド名はこの通りでなければなりません。つまり、`user-name` や `email` では動作しません。
ただし、フロントエンドで最終ユーザーにどう表示するかは自由です。
また、データベースのモデルでは任意の別名を使って構いません。
しかし、ログイン用の path operation では、仕様との互換性を保つたとえば組み込みのAPIドキュメントシステムを使えるようにするために、これらの名前を使う必要があります。
また、仕様では `username``password` はフォームデータとして送らなければならないつまり、ここではJSONは使わないことも定められています。
### `scope` { #scope }
仕様では、クライアントは追加のフォームフィールド「`scope`」を送ることができるとも書かれています。
フォームフィールド名は `scope`(単数形)ですが、実態はスペース区切りの「スコープ」文字列を並べた長い文字列です。
各「スコープ」は(スペースを含まない)単なる文字列です。
通常、特定のセキュリティ権限を宣言するために使われます。例えば:
- `users:read``users:write` はよくある例です。
- `instagram_basic` は Facebook / Instagram で使われます。
- `https://www.googleapis.com/auth/drive` は Google で使われます。
/// info | 情報
OAuth2 における「スコープ」は、要求される特定の権限を表す単なる文字列です。
`:` のような他の文字を含んでいても、URL であっても構いません。
それらの詳細は実装依存です。
OAuth2 にとっては単なる文字列です。
///
## `username``password` を取得するコード { #code-to-get-the-username-and-password }
では、これを処理するために **FastAPI** が提供するユーティリティを使いましょう。
### `OAuth2PasswordRequestForm` { #oauth2passwordrequestform }
まず、`OAuth2PasswordRequestForm` をインポートし、`/token` の path operation に `Depends` で依存関係として使います:
{* ../../docs_src/security/tutorial003_an_py310.py hl[4,78] *}
`OAuth2PasswordRequestForm` は次のフォームボディを宣言するクラス依存関係です:
- `username`
- `password`
- スペース区切りの文字列で構成される、オプションの `scope` フィールド
- オプションの `grant_type`
/// tip | 豆知識
OAuth2 の仕様では、固定値 `password` を持つフィールド `grant_type` が実際には必須ですが、`OAuth2PasswordRequestForm` はそれを強制しません。
強制したい場合は、`OAuth2PasswordRequestForm` の代わりに `OAuth2PasswordRequestFormStrict` を使ってください。
///
- オプションの `client_id`(この例では不要)
- オプションの `client_secret`(この例では不要)
/// info | 情報
`OAuth2PasswordRequestForm` は、`OAuth2PasswordBearer` のように **FastAPI** にとって特別なクラスではありません。
`OAuth2PasswordBearer`**FastAPI** にセキュリティスキームであることを認識させます。そのため OpenAPI にそのように追加されます。
一方、`OAuth2PasswordRequestForm` は、あなた自身でも書けるような単なるクラス依存関係であり、直接 `Form` パラメータを宣言することもできます。
ただし一般的なユースケースなので、簡単に使えるよう **FastAPI** が直接提供しています。
///
### フォームデータの利用 { #use-the-form-data }
/// tip | 豆知識
依存関係クラス `OAuth2PasswordRequestForm` のインスタンスは、スペース区切りの長い文字列を持つ `scope` 属性は持ちません。代わりに、送られてきた各スコープの実際の文字列リストを格納する `scopes` 属性を持ちます。
この例では `scopes` は使いませんが、必要ならその機能が利用できます。
///
次に、フォームフィールドの `username` を使って(疑似の)データベースからユーザーデータを取得します。
そのユーザーが存在しない場合は、「Incorrect username or password」というエラーを返します。
エラーには `HTTPException` 例外を使います:
{* ../../docs_src/security/tutorial003_an_py310.py hl[3,79:81] *}
### パスワードのチェック { #check-the-password }
この時点でデータベースからユーザーデータは取得できましたが、まだパスワードを確認していません。
まず、そのデータを Pydantic の `UserInDB` モデルに入れます。
プレーンテキストのパスワードを保存してはいけないので、(疑似の)パスワードハッシュ化システムを使います。
パスワードが一致しなければ、同じエラーを返します。
#### パスワードハッシュ化 { #password-hashing }
「ハッシュ化」とは、ある内容(ここではパスワード)を、乱雑に見えるバイト列(単なる文字列)に変換することを指します。
まったく同じ内容(まったく同じパスワード)を渡すと、毎回まったく同じ乱雑な文字列が得られます。
しかし、その乱雑な文字列から元のパスワードに戻すことはできません。
##### なぜパスワードをハッシュ化するのか { #why-use-password-hashing }
もしデータベースが盗まれても、盗んだ側が手にするのはユーザーのプレーンテキストのパスワードではなく、ハッシュだけです。
したがって、盗んだ側は同じパスワードを別のシステムで試すことができません(多くのユーザーがあらゆる場所で同じパスワードを使っているため、これは危険になり得ます)。
{* ../../docs_src/security/tutorial003_an_py310.py hl[82:85] *}
#### `**user_dict` について { #about-user-dict }
`UserInDB(**user_dict)` は次を意味します:
`user_dict` のキーと値を、そのままキーワード引数として渡します。つまり次と同等です:
```Python
UserInDB(
username = user_dict["username"],
email = user_dict["email"],
full_name = user_dict["full_name"],
disabled = user_dict["disabled"],
hashed_password = user_dict["hashed_password"],
)
```
/// info | 情報
`**user_dict` のより完全な解説は、[**追加モデル**のドキュメント](../extra-models.md#about-user-in-dict){.internal-link target=_blank}を参照してください。
///
## トークンを返す { #return-the-token }
`token` エンドポイントのレスポンスは JSON オブジェクトでなければなりません。
`token_type` を含める必要があります。ここでは「Bearer」トークンを使うので、トークンタイプは「`bearer`」です。
そして `access_token` を含め、その中にアクセストークンの文字列を入れます。
この単純な例では、完全に安全ではありませんが、トークンとして同じ `username` をそのまま返します。
/// tip | 豆知識
次の章では、パスワードハッシュ化と <abbr title="JSON Web Tokens - JSON Web Token">JWT</abbr> トークンを使った本当に安全な実装を見ます。
しかし今は、必要な特定の詳細に集中しましょう。
///
{* ../../docs_src/security/tutorial003_an_py310.py hl[87] *}
/// tip | 豆知識
仕様に従うと、この例と同じく `access_token``token_type` を含む JSON を返す必要があります。
これはあなた自身のコードで実装する必要があり、これらのJSONキーを使っていることを確認してください。
仕様に準拠するために、あなた自身が正しく覚えて実装すべきことは、ほぼこれだけです。
それ以外は **FastAPI** が面倒を見てくれます。
///
## 依存関係の更新 { #update-the-dependencies }
ここで依存関係を更新します。
アクティブなユーザーの場合にのみ `current_user` を取得したいとします。
そこで、`get_current_user` を依存関係として利用する追加の依存関係 `get_current_active_user` を作成します。
これら2つの依存関係は、ユーザーが存在しない、または非アクティブである場合に、HTTPエラーを返すだけです。
したがって、エンドポイントでは、ユーザーが存在し、正しく認証され、かつアクティブである場合にのみ、ユーザーを取得します:
{* ../../docs_src/security/tutorial003_an_py310.py hl[58:66,69:74,94] *}
/// info | 情報
ここで返している値が `Bearer` の追加ヘッダー `WWW-Authenticate` も仕様の一部です。
HTTPエラーステータスコード 401「UNAUTHORIZED」は、`WWW-Authenticate` ヘッダーも返すことになっています。
ベアラートークン(今回のケース)の場合、そのヘッダーの値は `Bearer` であるべきです。
実際のところ、この追加ヘッダーを省略しても動作はします。
しかし、仕様に準拠するためにここでは付与しています。
また、(今または将来)それを想定して利用するツールがあるかもしれず、あなたやユーザーにとって有用になる可能性があります。
これが標準の利点です…。
///
## 動作確認 { #see-it-in-action }
インタラクティブドキュメントを開きます: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>
### 認証 { #authenticate }
「Authorize」ボタンをクリックします。
次の認証情報を使います:
User: `johndoe`
Password: `secret`
<img src="/img/tutorial/security/image04.png">
システムで認証されると、次のように表示されます:
<img src="/img/tutorial/security/image05.png">
### 自分のユーザーデータを取得 { #get-your-own-user-data }
`GET` の path `/users/me` を使います。
次のようなユーザーデータが取得できます:
```JSON
{
"username": "johndoe",
"email": "johndoe@example.com",
"full_name": "John Doe",
"disabled": false,
"hashed_password": "fakehashedsecret"
}
```
<img src="/img/tutorial/security/image06.png">
錠前アイコンをクリックしてログアウトし、同じ操作を再度試すと、次のような HTTP 401 エラーになります:
```JSON
{
"detail": "Not authenticated"
}
```
### 非アクティブユーザー { #inactive-user }
今度は非アクティブなユーザーで試してみます。次で認証してください:
User: `alice`
Password: `secret2`
そして `GET` の path `/users/me` を使います。
次のような「Inactive user」エラーになります:
```JSON
{
"detail": "Inactive user"
}
```
## まとめ { #recap }
これで、API のために `username``password` に基づく完全なセキュリティシステムを実装するための道具が揃いました。
これらの道具を使えば、任意のデータベース、任意のユーザー/データモデルと互換性のあるセキュリティシステムを構築できます。
ただし、実際にはまだ「安全」ではありません。
次の章では、安全なパスワードハッシュライブラリと <abbr title="JSON Web Tokens - JSON Web Token">JWT</abbr> トークンの使い方を見ていきます。

Some files were not shown because too many files have changed in this diff Show More