mirror of
https://github.com/fastapi/fastapi.git
synced 2026-03-05 15:37:08 -05:00
🌐 Update translations for ja (update-outdated) (#14588)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Yurii Motov <yurii.motov.monte@gmail.com> Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com> Co-authored-by: Maruo.S <raspi-maru2004@outlook.jp>
This commit is contained in:
committed by
GitHub
parent
cec4be00ba
commit
b0e99d66e8
@@ -1,4 +1,4 @@
|
||||
# バックグラウンドタスク
|
||||
# バックグラウンドタスク { #background-tasks }
|
||||
|
||||
レスポンスを返した *後に* 実行されるバックグラウンドタスクを定義できます。
|
||||
|
||||
@@ -9,17 +9,17 @@
|
||||
* 作業実行後のメール通知:
|
||||
* メールサーバーへの接続とメールの送信は「遅い」(数秒) 傾向があるため、すぐにレスポンスを返し、バックグラウンドでメール通知ができます。
|
||||
* データ処理:
|
||||
* たとえば、時間のかかる処理を必要とするファイル受信時には、「受信済み」(HTTP 202) のレスポンスを返し、バックグラウンドで処理できます。
|
||||
* たとえば、時間のかかる処理を必要とするファイル受信時には、「Accepted」(HTTP 202) のレスポンスを返し、バックグラウンドで処理できます。
|
||||
|
||||
## `BackgroundTasks` の使用
|
||||
## `BackgroundTasks` の使用 { #using-backgroundtasks }
|
||||
|
||||
まず初めに、`BackgroundTasks` をインポートし、` BackgroundTasks` の型宣言と共に、*path operation 関数* のパラメーターを定義します:
|
||||
まず初めに、`BackgroundTasks` をインポートし、`BackgroundTasks` の型宣言と共に、*path operation function* のパラメーターを定義します:
|
||||
|
||||
{* ../../docs_src/background_tasks/tutorial001.py hl[1,13] *}
|
||||
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[1,13] *}
|
||||
|
||||
**FastAPI** は、`BackgroundTasks` 型のオブジェクトを作成し、そのパラメーターに渡します。
|
||||
|
||||
## タスク関数の作成
|
||||
## タスク関数の作成 { #create-a-task-function }
|
||||
|
||||
バックグラウンドタスクとして実行される関数を作成します。
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
|
||||
また、書き込み操作では `async` と `await` を使用しないため、通常の `def` で関数を定義します。
|
||||
|
||||
{* ../../docs_src/background_tasks/tutorial001.py hl[6:9] *}
|
||||
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[6:9] *}
|
||||
|
||||
## バックグラウンドタスクの追加
|
||||
## バックグラウンドタスクの追加 { #add-the-background-task }
|
||||
|
||||
*path operations 関数* 内で、`.add_task()` メソッドを使用してタスク関数を *background tasks* オブジェクトに渡します。
|
||||
*path operation function* 内で、`.add_task()` メソッドを使用してタスク関数を *background tasks* オブジェクトに渡します。
|
||||
|
||||
{* ../../docs_src/background_tasks/tutorial001.py hl[14] *}
|
||||
{* ../../docs_src/background_tasks/tutorial001_py39.py hl[14] *}
|
||||
|
||||
`.add_task()` は以下の引数を受け取ります:
|
||||
|
||||
@@ -45,40 +45,42 @@
|
||||
* タスク関数に順番に渡す必要のある引数の列 (`email`)。
|
||||
* タスク関数に渡す必要のあるキーワード引数 (`message="some notification"`)。
|
||||
|
||||
## 依存性注入
|
||||
## 依存性注入 { #dependency-injection }
|
||||
|
||||
`BackgroundTasks` の使用は依存性注入システムでも機能し、様々な階層 (*path operations 関数*、依存性 (依存可能性)、サブ依存性など) で `BackgroundTasks` 型のパラメーターを宣言できます。
|
||||
`BackgroundTasks` の使用は依存性注入システムでも機能し、様々な階層 (*path operation function*、依存性 (dependable)、サブ依存性など) で `BackgroundTasks` 型のパラメーターを宣言できます。
|
||||
|
||||
**FastAPI** は、それぞれの場合の処理方法と同じオブジェクトの再利用方法を知っているため、すべてのバックグラウンドタスクがマージされ、バックグラウンドで後で実行されます。
|
||||
**FastAPI** は、それぞれの場合の処理方法と同じオブジェクトの再利用方法を知っているため、すべてのバックグラウンドタスクがマージされ、バックグラウンドで後で実行されます:
|
||||
|
||||
|
||||
{* ../../docs_src/background_tasks/tutorial002_an_py310.py hl[13,15,22,25] *}
|
||||
|
||||
{* ../../docs_src/background_tasks/tutorial002.py hl[13,15,22,25] *}
|
||||
|
||||
この例では、レスポンスが送信された *後* にメッセージが `log.txt` ファイルに書き込まれます。
|
||||
|
||||
リクエストにクエリがあった場合、バックグラウンドタスクでログに書き込まれます。
|
||||
|
||||
そして、*path operations 関数* で生成された別のバックグラウンドタスクは、`email` パスパラメータを使用してメッセージを書き込みます。
|
||||
そして、*path operation function* で生成された別のバックグラウンドタスクは、`email` パスパラメータを使用してメッセージを書き込みます。
|
||||
|
||||
## 技術的な詳細
|
||||
## 技術的な詳細 { #technical-details }
|
||||
|
||||
`BackgroundTasks` クラスは、<a href="https://www.starlette.dev/background/" class="external-link" target="_blank">`starlette.background`</a>から直接取得されます。
|
||||
|
||||
これは、FastAPI に直接インポート/インクルードされるため、`fastapi` からインポートできる上に、`starlette.background`から別の `BackgroundTask` (末尾に `s` がない) を誤ってインポートすることを回避できます。
|
||||
|
||||
`BackgroundTasks`のみを使用することで (`BackgroundTask` ではなく)、`Request` オブジェクトを直接使用する場合と同様に、それを *path operations 関数* パラメーターとして使用し、**FastAPI** に残りの処理を任せることができます。
|
||||
`BackgroundTasks`のみを使用することで (`BackgroundTask` ではなく)、`Request` オブジェクトを直接使用する場合と同様に、それを *path operation function* パラメーターとして使用し、**FastAPI** に残りの処理を任せることができます。
|
||||
|
||||
それでも、FastAPI で `BackgroundTask` を単独で使用することは可能ですが、コード内でオブジェクトを作成し、それを含むStarlette `Response` を返す必要があります。
|
||||
|
||||
詳細については、<a href="https://www.starlette.dev/background/" class="external-link" target="_blank">バックグラウンドタスクに関する Starlette の公式ドキュメント</a>を参照して下さい。
|
||||
詳細については、<a href="https://www.starlette.dev/background/" class="external-link" target="_blank">Starlette のバックグラウンドタスクに関する公式ドキュメント</a>を参照して下さい。
|
||||
|
||||
## 警告
|
||||
## 注意 { #caveat }
|
||||
|
||||
大量のバックグラウンド計算が必要であり、必ずしも同じプロセスで実行する必要がない場合 (たとえば、メモリや変数などを共有する必要がない場合)、<a href="https://www.celeryproject.org/" class="external-link" target="_blank">Celery</a> のようなより大きな他のツールを使用するとメリットがあるかもしれません。
|
||||
大量のバックグラウンド計算が必要であり、必ずしも同じプロセスで実行する必要がない場合 (たとえば、メモリや変数などを共有する必要がない場合)、<a href="https://docs.celeryq.dev" class="external-link" target="_blank">Celery</a> のようなより大きな他のツールを使用するとメリットがあるかもしれません。
|
||||
|
||||
これらは、より複雑な構成、RabbitMQ や Redis などのメッセージ/ジョブキューマネージャーを必要とする傾向がありますが、複数のプロセス、特に複数のサーバーでバックグラウンドタスクを実行できます。
|
||||
|
||||
ただし、同じ **FastAPI** アプリから変数とオブジェクトにアクセスする必要がある場合、または小さなバックグラウンドタスク (電子メール通知の送信など) を実行する必要がある場合は、単に `BackgroundTasks` を使用できます。
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
`BackgroundTasks` をインポートして、*path operations 関数* や依存関係のパラメータに `BackgroundTasks`を使用し、バックグラウンドタスクを追加して下さい。
|
||||
*path operation functions* と依存性のパラメータで `BackgroundTasks`をインポートして使用し、バックグラウンドタスクを追加して下さい。
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# ボディ - フィールド
|
||||
# ボディ - フィールド { #body-fields }
|
||||
|
||||
`Query`や`Path`、`Body`を使って *path operation関数* のパラメータに追加のバリデーションやメタデータを宣言するのと同じように、Pydanticの`Field`を使ってPydanticモデルの内部でバリデーションやメタデータを宣言することができます。
|
||||
|
||||
## `Field`のインポート
|
||||
## `Field`のインポート { #import-field }
|
||||
|
||||
まず、以下のようにインポートします:
|
||||
|
||||
{* ../../docs_src/body_fields/tutorial001.py hl[4] *}
|
||||
{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[4] *}
|
||||
|
||||
|
||||
/// warning | 注意
|
||||
|
||||
@@ -14,11 +15,11 @@
|
||||
|
||||
///
|
||||
|
||||
## モデルの属性の宣言
|
||||
## モデルの属性の宣言 { #declare-model-attributes }
|
||||
|
||||
以下のように`Field`をモデルの属性として使用することができます:
|
||||
|
||||
{* ../../docs_src/body_fields/tutorial001.py hl[11,12,13,14] *}
|
||||
{* ../../docs_src/body_fields/tutorial001_an_py310.py hl[11:14] *}
|
||||
|
||||
`Field`は`Query`や`Path`、`Body`と同じように動作し、全く同様のパラメータなどを持ちます。
|
||||
|
||||
@@ -40,13 +41,20 @@
|
||||
|
||||
///
|
||||
|
||||
## 追加情報の追加
|
||||
## 追加情報の追加 { #add-extra-information }
|
||||
|
||||
追加情報は`Field`や`Query`、`Body`などで宣言することができます。そしてそれは生成されたJSONスキーマに含まれます。
|
||||
|
||||
後に例を用いて宣言を学ぶ際に、追加情報を追加する方法を学べます。
|
||||
|
||||
## まとめ
|
||||
/// warning | 注意
|
||||
|
||||
`Field`に渡された追加のキーは、結果として生成されるアプリケーションのOpenAPIスキーマにも含まれます。
|
||||
これらのキーは必ずしもOpenAPI仕様の一部であるとは限らないため、例えば[OpenAPI validator](https://validator.swagger.io/)などの一部のOpenAPIツールは、生成されたスキーマでは動作しない場合があります。
|
||||
|
||||
///
|
||||
|
||||
## まとめ { #recap }
|
||||
|
||||
Pydanticの`Field`を使用して、モデルの属性に追加のバリデーションやメタデータを宣言することができます。
|
||||
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
# ボディ - 複数のパラメータ
|
||||
# ボディ - 複数のパラメータ { #body-multiple-parameters }
|
||||
|
||||
これまで`Path`と`Query`をどう使うかを見てきましたが、リクエストボディの宣言のより高度な使い方を見てみましょう。
|
||||
これまで`Path`と`Query`をどう使うかを見てきましたが、リクエストボディ宣言のより高度な使い方を見てみましょう。
|
||||
|
||||
## `Path`、`Query`とボディパラメータを混ぜる
|
||||
## `Path`、`Query`とボディパラメータを混ぜる { #mix-path-query-and-body-parameters }
|
||||
|
||||
まず、もちろん、`Path`と`Query`とリクエストボディのパラメータの宣言は自由に混ぜることができ、 **FastAPI** は何をするべきかを知っています。
|
||||
まず、もちろん、`Path`と`Query`とリクエストボディのパラメータ宣言は自由に混ぜることができ、 **FastAPI** は何をするべきかを知っています。
|
||||
|
||||
また、デフォルトの`None`を設定することで、ボディパラメータをオプションとして宣言することもできます:
|
||||
また、デフォルトを`None`に設定することで、ボディパラメータをオプションとして宣言することもできます:
|
||||
|
||||
{* ../../docs_src/body_multiple_params/tutorial001.py hl[19,20,21] *}
|
||||
{* ../../docs_src/body_multiple_params/tutorial001_an_py310.py hl[18:20] *}
|
||||
|
||||
/// note | 備考
|
||||
|
||||
この場合、ボディから取得する`item`はオプションであることに注意してください。デフォルト値は`None`です。
|
||||
この場合、ボディから取得する`item`はオプションであることに注意してください。デフォルト値が`None`になっているためです。
|
||||
|
||||
///
|
||||
|
||||
## 複数のボディパラメータ
|
||||
## 複数のボディパラメータ { #multiple-body-parameters }
|
||||
|
||||
上述の例では、*path operations*は`item`の属性を持つ以下のようなJSONボディを期待していました:
|
||||
上述の例では、*path operations*は`Item`の属性を持つ以下のようなJSONボディを期待していました:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -31,11 +31,12 @@
|
||||
|
||||
しかし、`item`と`user`のように複数のボディパラメータを宣言することもできます:
|
||||
|
||||
{* ../../docs_src/body_multiple_params/tutorial002.py hl[22] *}
|
||||
{* ../../docs_src/body_multiple_params/tutorial002_py310.py hl[20] *}
|
||||
|
||||
この場合、**FastAPI**は関数内に複数のボディパラメータ(Pydanticモデルである2つのパラメータ)があることに気付きます。
|
||||
|
||||
そのため、パラメータ名をボディのキー(フィールド名)として使用し、以下のようなボディを期待しています:
|
||||
この場合、**FastAPI**は関数内に複数のボディパラメータがあることに気付きます(Pydanticモデルである2つのパラメータがあります)。
|
||||
|
||||
そのため、パラメータ名をボディのキー(フィールド名)として使用し、以下のようなボディを期待します:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -62,7 +63,7 @@
|
||||
|
||||
複合データの検証を行い、OpenAPIスキーマや自動ドキュメントのように文書化してくれます。
|
||||
|
||||
## ボディ内の単数値
|
||||
## ボディ内の単数値 { #singular-values-in-body }
|
||||
|
||||
クエリとパスパラメータの追加データを定義するための `Query` と `Path` があるのと同じように、 **FastAPI** は同等の `Body` を提供します。
|
||||
|
||||
@@ -72,12 +73,11 @@
|
||||
|
||||
しかし、`Body`を使用して、**FastAPI** に別のボディキーとして扱うように指示することができます:
|
||||
|
||||
{* ../../docs_src/body_multiple_params/tutorial003_an_py310.py hl[23] *}
|
||||
|
||||
{* ../../docs_src/body_multiple_params/tutorial003.py hl[23] *}
|
||||
|
||||
この場合、**FastAPI** は以下のようなボディを期待します:
|
||||
|
||||
|
||||
```JSON
|
||||
{
|
||||
"item": {
|
||||
@@ -96,41 +96,48 @@
|
||||
|
||||
繰り返しになりますが、データ型の変換、検証、文書化などを行います。
|
||||
|
||||
## 複数のボディパラメータとクエリ
|
||||
## 複数のボディパラメータとクエリ { #multiple-body-params-and-query }
|
||||
|
||||
もちろん、ボディパラメータに加えて、必要に応じて追加のクエリパラメータを宣言することもできます。
|
||||
|
||||
デフォルトでは、単数値はクエリパラメータとして解釈されるので、明示的に `Query` を追加する必要はありません。
|
||||
デフォルトでは、単数値はクエリパラメータとして解釈されるので、明示的に `Query` を追加する必要はなく、次のようにできます:
|
||||
|
||||
```Python
|
||||
q: str = None
|
||||
q: str | None = None
|
||||
```
|
||||
|
||||
以下において:
|
||||
またはPython 3.10以上では:
|
||||
|
||||
{* ../../docs_src/body_multiple_params/tutorial004.py hl[27] *}
|
||||
```Python
|
||||
q: Union[str, None] = None
|
||||
```
|
||||
|
||||
例えば:
|
||||
|
||||
{* ../../docs_src/body_multiple_params/tutorial004_an_py310.py hl[28] *}
|
||||
|
||||
/// info | 情報
|
||||
|
||||
`Body`もまた、後述する `Query` や `Path` などと同様に、すべての検証パラメータとメタデータパラメータを持っています。
|
||||
`Body`もまた、後述する `Query` や `Path` などと同様に、すべての追加検証パラメータとメタデータパラメータを持っています。
|
||||
|
||||
///
|
||||
|
||||
## 単一のボディパラメータの埋め込み
|
||||
## 単一のボディパラメータの埋め込み { #embed-a-single-body-parameter }
|
||||
|
||||
Pydanticモデル`Item`のボディパラメータ`item`を1つだけ持っているとしましょう。
|
||||
Pydanticモデル`Item`の単一の`item`ボディパラメータしかないとしましょう。
|
||||
|
||||
デフォルトでは、**FastAPI**はそのボディを直接期待します。
|
||||
|
||||
しかし、追加のボディパラメータを宣言したときのように、キー `item` を持つ JSON とその中のモデルの内容を期待したい場合は、特別な `Body` パラメータ `embed` を使うことができます:
|
||||
しかし、追加のボディパラメータを宣言したときのように、キー `item` を持つ JSON と、その中のモデル内容を期待したい場合は、特別な `Body` パラメータ `embed` を使うことができます:
|
||||
|
||||
```Python
|
||||
item: Item = Body(..., embed=True)
|
||||
item: Item = Body(embed=True)
|
||||
```
|
||||
|
||||
以下において:
|
||||
|
||||
{* ../../docs_src/body_multiple_params/tutorial005.py hl[17] *}
|
||||
{* ../../docs_src/body_multiple_params/tutorial005_an_py310.py hl[17] *}
|
||||
|
||||
|
||||
この場合、**FastAPI** は以下のようなボディを期待します:
|
||||
|
||||
@@ -156,9 +163,9 @@ item: Item = Body(..., embed=True)
|
||||
}
|
||||
```
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
リクエストが単一のボディしか持てない場合でも、*path operation関数*に複数のボディパラメータを追加することができます。
|
||||
リクエストが単一のボディしか持てない場合でも、*path operation function*に複数のボディパラメータを追加することができます。
|
||||
|
||||
しかし、**FastAPI** はそれを処理し、関数内の正しいデータを与え、*path operation*内の正しいスキーマを検証し、文書化します。
|
||||
|
||||
|
||||
@@ -1,36 +1,26 @@
|
||||
# ボディ - ネストされたモデル
|
||||
# ボディ - ネストされたモデル { #body-nested-models }
|
||||
|
||||
**FastAPI** を使用すると、深くネストされた任意のモデルを定義、検証、文書化、使用することができます(Pydanticのおかげです)。
|
||||
|
||||
## リストのフィールド
|
||||
## リストのフィールド { #list-fields }
|
||||
|
||||
属性をサブタイプとして定義することができます。例えば、Pythonの`list`は以下のように定義できます:
|
||||
属性をサブタイプとして定義することができます。例えば、Pythonの`list`:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial001.py hl[12] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial001_py310.py hl[12] *}
|
||||
|
||||
これにより、各項目の型は宣言されていませんが、`tags`はある項目のリストになります。
|
||||
これにより、各項目の型は宣言されていませんが、`tags`はリストになります。
|
||||
|
||||
## タイプパラメータを持つリストのフィールド
|
||||
## タイプパラメータを持つリストのフィールド { #list-fields-with-type-parameter }
|
||||
|
||||
しかし、Pythonには型や「タイプパラメータ」を使ってリストを宣言する方法があります:
|
||||
しかし、Pythonには内部の型、または「タイプパラメータ」を使ってリストを宣言するための特定の方法があります:
|
||||
|
||||
### typingの`List`をインポート
|
||||
### タイプパラメータを持つ`list`の宣言 { #declare-a-list-with-a-type-parameter }
|
||||
|
||||
まず、Pythonの標準の`typing`モジュールから`List`をインポートします:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial002.py hl[1] *}
|
||||
|
||||
### タイプパラメータを持つ`List`の宣言
|
||||
|
||||
`list`や`dict`、`tuple`のようなタイプパラメータ(内部の型)を持つ型を宣言するには:
|
||||
|
||||
* `typing`モジュールからそれらをインストールします。
|
||||
* 角括弧(`[`と`]`)を使って「タイプパラメータ」として内部の型を渡します:
|
||||
`list`、`dict`、`tuple`のようにタイプパラメータ(内部の型)を持つ型を宣言するには、
|
||||
角括弧(`[`と`]`)を使って内部の型を「タイプパラメータ」として渡します。
|
||||
|
||||
```Python
|
||||
from typing import List
|
||||
|
||||
my_list: List[str]
|
||||
my_list: list[str]
|
||||
```
|
||||
|
||||
型宣言の標準的なPythonの構文はこれだけです。
|
||||
@@ -39,17 +29,17 @@ my_list: List[str]
|
||||
|
||||
そのため、以下の例では`tags`を具体的な「文字列のリスト」にすることができます:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial002.py hl[14] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial002_py310.py hl[12] *}
|
||||
|
||||
## セット型
|
||||
## セット型 { #set-types }
|
||||
|
||||
しかし、よく考えてみると、タグは繰り返すべきではなく、おそらくユニークな文字列になるのではないかと気付いたとします。
|
||||
|
||||
そして、Pythonにはユニークな項目のセットのための特別なデータ型`set`があります。
|
||||
|
||||
そのため、以下のように、`Set`をインポートして`str`の`set`として`tags`を宣言することができます:
|
||||
そして、`tags`を文字列のセットとして宣言できます:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial003.py hl[1,14] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial003_py310.py hl[12] *}
|
||||
|
||||
これを使えば、データが重複しているリクエストを受けた場合でも、ユニークな項目のセットに変換されます。
|
||||
|
||||
@@ -57,27 +47,27 @@ my_list: List[str]
|
||||
|
||||
また、それに応じて注釈をつけたり、文書化したりします。
|
||||
|
||||
## ネストされたモデル
|
||||
## ネストされたモデル { #nested-models }
|
||||
|
||||
Pydanticモデルの各属性には型があります。
|
||||
|
||||
しかし、その型はそれ自体が別のPydanticモデルである可能性があります。
|
||||
|
||||
そのため、特定の属性名、型、バリデーションを指定して、深くネストしたJSON`object`を宣言することができます。
|
||||
そのため、特定の属性名、型、バリデーションを指定して、深くネストしたJSON「オブジェクト」を宣言することができます。
|
||||
|
||||
すべては、任意のネストにされています。
|
||||
|
||||
### サブモデルの定義
|
||||
### サブモデルの定義 { #define-a-submodel }
|
||||
|
||||
例えば、`Image`モデルを定義することができます:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial004.py hl[9,10,11] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[7:9] *}
|
||||
|
||||
### サブモデルを型として使用
|
||||
### サブモデルを型として使用 { #use-the-submodel-as-a-type }
|
||||
|
||||
そして、それを属性の型として使用することができます:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial004.py hl[20] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial004_py310.py hl[18] *}
|
||||
|
||||
これは **FastAPI** が以下のようなボディを期待することを意味します:
|
||||
|
||||
@@ -102,23 +92,23 @@ Pydanticモデルの各属性には型があります。
|
||||
* データの検証
|
||||
* 自動文書化
|
||||
|
||||
## 特殊な型とバリデーション
|
||||
## 特殊な型とバリデーション { #special-types-and-validation }
|
||||
|
||||
`str`や`int`、`float`のような通常の単数型の他にも、`str`を継承したより複雑な単数型を使うこともできます。
|
||||
`str`や`int`、`float`などの通常の単数型の他にも、`str`を継承したより複雑な単数型を使うこともできます。
|
||||
|
||||
すべてのオプションをみるには、<a href="https://docs.pydantic.dev/latest/concepts/types/" class="external-link" target="_blank">Pydanticのエキゾチック な型</a>のドキュメントを確認してください。次の章でいくつかの例をみることができます。
|
||||
すべてのオプションをみるには、<a href="https://docs.pydantic.dev/latest/concepts/types/" class="external-link" target="_blank">Pydanticの型の概要</a>を確認してください。次の章でいくつかの例をみることができます。
|
||||
|
||||
例えば、`Image`モデルのように`url`フィールドがある場合、`str`の代わりにPydanticの`HttpUrl`を指定することができます:
|
||||
例えば、`Image`モデルのように`url`フィールドがある場合、`str`の代わりにPydanticの`HttpUrl`のインスタンスとして宣言することができます:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial005.py hl[4,10] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial005_py310.py hl[2,8] *}
|
||||
|
||||
文字列は有効なURLであることが確認され、そのようにJSONスキーマ・OpenAPIで文書化されます。
|
||||
文字列は有効なURLであることが確認され、そのようにJSON Schema / OpenAPIで文書化されます。
|
||||
|
||||
## サブモデルのリストを持つ属性
|
||||
## サブモデルのリストを持つ属性 { #attributes-with-lists-of-submodels }
|
||||
|
||||
Pydanticモデルを`list`や`set`などのサブタイプとして使用することもできます:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial006.py hl[20] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial006_py310.py hl[18] *}
|
||||
|
||||
これは、次のようなJSONボディを期待します(変換、検証、ドキュメントなど):
|
||||
|
||||
@@ -152,59 +142,59 @@ Pydanticモデルを`list`や`set`などのサブタイプとして使用する
|
||||
|
||||
///
|
||||
|
||||
## 深くネストされたモデル
|
||||
## 深くネストされたモデル { #deeply-nested-models }
|
||||
|
||||
深くネストされた任意のモデルを定義することができます:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial007.py hl[9,14,20,23,27] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial007_py310.py hl[7,12,18,21,25] *}
|
||||
|
||||
/// info | 情報
|
||||
|
||||
`Offer`は`Item`のリストであり、オプションの`Image`のリストを持っていることに注目してください。
|
||||
`Offer`は`Item`のリストであり、それらがさらにオプションの`Image`のリストを持っていることに注目してください。
|
||||
|
||||
///
|
||||
|
||||
## 純粋なリストのボディ
|
||||
## 純粋なリストのボディ { #bodies-of-pure-lists }
|
||||
|
||||
期待するJSONボディのトップレベルの値がJSON`array`(Pythonの`list`)であれば、Pydanticモデルと同じように、関数のパラメータで型を宣言することができます:
|
||||
|
||||
```Python
|
||||
images: List[Image]
|
||||
images: list[Image]
|
||||
```
|
||||
|
||||
以下のように:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial008.py hl[15] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial008_py39.py hl[13] *}
|
||||
|
||||
## あらゆる場所でのエディタサポート
|
||||
## あらゆる場所でのエディタサポート { #editor-support-everywhere }
|
||||
|
||||
エディタのサポートもどこでも受けることができます。
|
||||
そして、あらゆる場所でエディタサポートを得られます。
|
||||
|
||||
以下のようにリストの中の項目でも:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/body-nested-models/image01.png">
|
||||
<img src="/img/tutorial/body-nested-models/image01.png">
|
||||
|
||||
Pydanticモデルではなく、`dict`を直接使用している場合はこのようなエディタのサポートは得られません。
|
||||
|
||||
しかし、それらについて心配する必要はありません。入力された辞書は自動的に変換され、出力も自動的にJSONに変換されます。
|
||||
しかし、それらについて心配する必要はありません。入力されたdictは自動的に変換され、出力も自動的にJSONに変換されます。
|
||||
|
||||
## 任意の`dict`のボディ
|
||||
## 任意の`dict`のボディ { #bodies-of-arbitrary-dicts }
|
||||
|
||||
また、ある型のキーと別の型の値を持つ`dict`としてボディを宣言することもできます。
|
||||
|
||||
有効なフィールド・属性名を事前に知る必要がありません(Pydanticモデルの場合のように)。
|
||||
この方法で、有効なフィールド/属性名を事前に知る必要がありません(Pydanticモデルの場合のように)。
|
||||
|
||||
これは、まだ知らないキーを受け取りたいときに便利だと思います。
|
||||
これは、まだ知らないキーを受け取りたいときに便利です。
|
||||
|
||||
---
|
||||
|
||||
他にも、`int`のように他の型のキーを持ちたい場合などに便利です。
|
||||
もうひとつ便利なケースは、別の型(例: `int`)のキーを持ちたい場合です。
|
||||
|
||||
それをここで見ていきましょう。
|
||||
それをここで見ていきます。
|
||||
|
||||
この場合、`int`のキーと`float`の値を持つものであれば、どんな`dict`でも受け入れることができます:
|
||||
|
||||
{* ../../docs_src/body_nested_models/tutorial009.py hl[15] *}
|
||||
{* ../../docs_src/body_nested_models/tutorial009_py39.py hl[7] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
@@ -218,14 +208,14 @@ JSONはキーとして`str`しかサポートしていないことに注意し
|
||||
|
||||
///
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
**FastAPI** を使用すると、Pydanticモデルが提供する最大限の柔軟性を持ちながら、コードをシンプルに短く、エレガントに保つことができます。
|
||||
|
||||
以下のような利点があります:
|
||||
しかし、以下のような利点があります:
|
||||
|
||||
* エディタのサポート(どこでも補完!)
|
||||
* データ変換(別名:構文解析・シリアライズ)
|
||||
* データ変換(別名:構文解析 / シリアライズ)
|
||||
* データの検証
|
||||
* スキーマ文書
|
||||
* 自動文書化
|
||||
* 自動ドキュメント
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# ボディ - 更新
|
||||
# ボディ - 更新 { #body-updates }
|
||||
|
||||
## `PUT`による置換での更新
|
||||
## `PUT`による置換での更新 { #update-replacing-with-put }
|
||||
|
||||
項目を更新するには<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT" class="external-link" target="_blank">HTTPの`PUT`</a>操作を使用することができます。
|
||||
|
||||
`jsonable_encoder`を用いて、入力データをJSON形式で保存できるデータに変換することができます(例:NoSQLデータベース)。例えば、`datetime`を`str`に変換します。
|
||||
`jsonable_encoder`を用いて、入力データをJSONとして保存できるデータに変換することができます(例:NoSQLデータベース)。例えば、`datetime`を`str`に変換します。
|
||||
|
||||
{* ../../docs_src/body_updates/tutorial001.py hl[30,31,32,33,34,35] *}
|
||||
{* ../../docs_src/body_updates/tutorial001_py310.py hl[28:33] *}
|
||||
|
||||
既存のデータを置き換えるべきデータを受け取るために`PUT`は使用されます。
|
||||
`PUT`は、既存のデータを置き換えるべきデータを受け取るために使用されます。
|
||||
|
||||
### 置換についての注意
|
||||
### 置換についての注意 { #warning-about-replacing }
|
||||
|
||||
つまり、`PUT`を使用して以下のボディで項目`bar`を更新したい場合は:
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
}
|
||||
```
|
||||
|
||||
すでに格納されている属性`"tax": 20.2`を含まないため、入力モデルのデフォルト値は`"tax": 10.5`です。
|
||||
すでに格納されている属性`"tax": 20.2`を含まないため、入力モデルは`"tax": 10.5`のデフォルト値を取ります。
|
||||
|
||||
そして、データはその「新しい」`10.5`の`tax`と共に保存されます。
|
||||
|
||||
## `PATCH`による部分的な更新
|
||||
## `PATCH`による部分的な更新 { #partial-updates-with-patch }
|
||||
|
||||
また、<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH" class="external-link" target="_blank">HTTPの`PATCH`</a>操作でデータを*部分的に*更新することもできます。
|
||||
|
||||
@@ -44,27 +44,27 @@
|
||||
|
||||
///
|
||||
|
||||
### Pydanticの`exclude_unset`パラメータの使用
|
||||
### Pydanticの`exclude_unset`パラメータの使用 { #using-pydantics-exclude-unset-parameter }
|
||||
|
||||
部分的な更新を受け取りたい場合は、Pydanticモデルの`.dict()`の`exclude_unset`パラメータを使用すると非常に便利です。
|
||||
部分的な更新を受け取りたい場合は、Pydanticモデルの`.model_dump()`の`exclude_unset`パラメータを使用すると非常に便利です。
|
||||
|
||||
`item.dict(exclude_unset=True)`のように。
|
||||
`item.model_dump(exclude_unset=True)`のように。
|
||||
|
||||
これにより、`item`モデルの作成時に設定されたデータのみを持つ`dict`が生成され、デフォルト値は除外されます。
|
||||
|
||||
これを使うことで、デフォルト値を省略して、設定された(リクエストで送られた)データのみを含む`dict`を生成することができます:
|
||||
|
||||
{* ../../docs_src/body_updates/tutorial002.py hl[34] *}
|
||||
{* ../../docs_src/body_updates/tutorial002_py310.py hl[32] *}
|
||||
|
||||
### Pydanticの`update`パラメータ
|
||||
### Pydanticの`update`パラメータの使用 { #using-pydantics-update-parameter }
|
||||
|
||||
ここで、`.copy()`を用いて既存のモデルのコピーを作成し、`update`パラメータに更新するデータを含む`dict`を渡すことができます。
|
||||
ここで、`.model_copy()`を用いて既存のモデルのコピーを作成し、`update`パラメータに更新するデータを含む`dict`を渡すことができます。
|
||||
|
||||
`stored_item_model.copy(update=update_data)`のように:
|
||||
`stored_item_model.model_copy(update=update_data)`のように:
|
||||
|
||||
{* ../../docs_src/body_updates/tutorial002.py hl[35] *}
|
||||
{* ../../docs_src/body_updates/tutorial002_py310.py hl[33] *}
|
||||
|
||||
### 部分的更新のまとめ
|
||||
### 部分的更新のまとめ { #partial-updates-recap }
|
||||
|
||||
まとめると、部分的な更新を適用するには、次のようにします:
|
||||
|
||||
@@ -75,11 +75,11 @@
|
||||
* この方法では、モデル内のデフォルト値ですでに保存されている値を上書きするのではなく、ユーザーが実際に設定した値のみを更新することができます。
|
||||
* 保存されているモデルのコピーを作成し、受け取った部分的な更新で属性を更新します(`update`パラメータを使用します)。
|
||||
* コピーしたモデルをDBに保存できるものに変換します(例えば、`jsonable_encoder`を使用します)。
|
||||
* これはモデルの`.dict()`メソッドを再度利用することに匹敵しますが、値をJSONに変換できるデータ型、例えば`datetime`を`str`に変換します。
|
||||
* これはモデルの`.model_dump()`メソッドを再度利用することに匹敵しますが、値をJSONに変換できるデータ型になるようにし(変換し)、例えば`datetime`を`str`に変換します。
|
||||
* データをDBに保存します。
|
||||
* 更新されたモデルを返します。
|
||||
|
||||
{* ../../docs_src/body_updates/tutorial002.py hl[30,31,32,33,34,35,36,37] *}
|
||||
{* ../../docs_src/body_updates/tutorial002_py310.py hl[28:35] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
|
||||
@@ -1,40 +1,41 @@
|
||||
# リクエストボディ
|
||||
# リクエストボディ { #request-body }
|
||||
|
||||
クライアント (ブラウザなど) からAPIにデータを送信する必要があるとき、データを **リクエストボディ (request body)** として送ります。
|
||||
クライアント(例えばブラウザ)からAPIにデータを送信する必要がある場合、**リクエストボディ**として送信します。
|
||||
|
||||
**リクエスト** ボディはクライアントによってAPIへ送られます。**レスポンス** ボディはAPIがクライアントに送るデータです。
|
||||
**リクエスト**ボディは、クライアントからAPIへ送信されるデータです。**レスポンス**ボディは、APIがクライアントに送信するデータです。
|
||||
|
||||
APIはほとんどの場合 **レスポンス** ボディを送らなければなりません。しかし、クライアントは必ずしも **リクエスト** ボディを送らなければいけないわけではありません。
|
||||
APIはほとんどの場合 **レスポンス** ボディを送信する必要があります。しかしクライアントは、常に **リクエストボディ** を送信する必要があるとは限りません。場合によっては、クエリパラメータ付きのパスだけをリクエストして、ボディを送信しないこともあります。
|
||||
|
||||
**リクエスト** ボディを宣言するために <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> モデルを使用し、その強力な機能とメリットをすべて利用します。
|
||||
|
||||
/// info | 情報
|
||||
|
||||
データを送るには、`POST` (もっともよく使われる)、`PUT`、`DELETE` または `PATCH` を使うべきです。
|
||||
データを送信するには、`POST`(より一般的)、`PUT`、`DELETE`、`PATCH` のいずれかを使用すべきです。
|
||||
|
||||
GET リクエストでボディを送信することは、仕様では未定義の動作ですが、FastAPI でサポートされており、非常に複雑な(極端な)ユースケースにのみ対応しています。
|
||||
`GET` リクエストでボディを送信することは仕様上は未定義の動作ですが、それでもFastAPIではサポートされています。ただし、非常に複雑/極端なユースケースのためだけです。
|
||||
|
||||
非推奨なので、Swagger UIを使った対話型のドキュメントにはGETのボディ情報は表示されません。さらに、中継するプロキシが対応していない可能性があります。
|
||||
推奨されないため、Swagger UIによる対話的ドキュメントでは `GET` 使用時のボディのドキュメントは表示されず、途中のプロキシが対応していない可能性もあります。
|
||||
|
||||
///
|
||||
|
||||
## Pydanticの `BaseModel` をインポート
|
||||
## Pydanticの `BaseModel` をインポート { #import-pydantics-basemodel }
|
||||
|
||||
ます初めに、 `pydantic` から `BaseModel` をインポートする必要があります:
|
||||
まず、`pydantic` から `BaseModel` をインポートする必要があります:
|
||||
|
||||
{* ../../docs_src/body/tutorial001.py hl[4] *}
|
||||
{* ../../docs_src/body/tutorial001_py310.py hl[2] *}
|
||||
|
||||
## データモデルの作成
|
||||
## データモデルの作成 { #create-your-data-model }
|
||||
|
||||
そして、`BaseModel` を継承したクラスとしてデータモデルを宣言します。
|
||||
次に、`BaseModel` を継承するクラスとしてデータモデルを宣言します。
|
||||
|
||||
すべての属性にpython標準の型を使用します:
|
||||
すべての属性に標準のPython型を使用します:
|
||||
|
||||
{* ../../docs_src/body/tutorial001.py hl[7:11] *}
|
||||
{* ../../docs_src/body/tutorial001_py310.py hl[5:9] *}
|
||||
|
||||
クエリパラメータの宣言と同様に、モデル属性がデフォルト値をもつとき、必須な属性ではなくなります。それ以外は必須になります。オプショナルな属性にしたい場合は `None` を使用してください。
|
||||
|
||||
例えば、上記のモデルは以下の様なJSON「`オブジェクト`」(もしくはPythonの `dict` ) を宣言しています:
|
||||
クエリパラメータの宣言と同様に、モデル属性がデフォルト値を持つ場合は必須ではありません。そうでなければ必須です。単にオプションにするには `None` を使用してください。
|
||||
|
||||
例えば、上記のモデルは次のようなJSON「`object`」(またはPythonの `dict`)を宣言します:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -45,7 +46,7 @@ GET リクエストでボディを送信することは、仕様では未定義
|
||||
}
|
||||
```
|
||||
|
||||
...`description` と `tax` はオプショナル (デフォルト値は `None`) なので、以下のJSON「`オブジェクト`」も有効です:
|
||||
...`description` と `tax` はオプション(デフォルト値が `None`)なので、このJSON「`object`」も有効です:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -54,109 +55,112 @@ GET リクエストでボディを送信することは、仕様では未定義
|
||||
}
|
||||
```
|
||||
|
||||
## パラメータとして宣言
|
||||
## パラメータとして宣言 { #declare-it-as-a-parameter }
|
||||
|
||||
*パスオペレーション* に加えるために、パスパラメータやクエリパラメータと同じ様に宣言します:
|
||||
*path operation* に追加するには、パスパラメータやクエリパラメータを宣言したのと同じ方法で宣言します:
|
||||
|
||||
{* ../../docs_src/body/tutorial001.py hl[18] *}
|
||||
{* ../../docs_src/body/tutorial001_py310.py hl[16] *}
|
||||
|
||||
...そして、作成したモデル `Item` で型を宣言します。
|
||||
...そして、作成したモデル `Item` を型として宣言します。
|
||||
|
||||
## 結果
|
||||
## 結果 { #results }
|
||||
|
||||
そのPythonの型宣言だけで **FastAPI** は以下のことを行います:
|
||||
そのPythonの型宣言だけで **FastAPI** は以下を行います:
|
||||
|
||||
* リクエストボディをJSONとして読み取ります。
|
||||
* 適当な型に変換します(必要な場合)。
|
||||
* リクエストのボディをJSONとして読み取ります。
|
||||
* 対応する型に変換します(必要な場合)。
|
||||
* データを検証します。
|
||||
* データが無効な場合は、明確なエラーが返され、どこが不正なデータであったかを示します。
|
||||
* 受け取ったデータをパラメータ `item` に変換します。
|
||||
* 関数内で `Item` 型であると宣言したので、すべての属性とその型に対するエディタサポート(補完など)をすべて使用できます。
|
||||
* モデルの<a href="http://json-schema.org" class="external-link" target="_blank">JSONスキーマ</a>定義を生成し、好きな場所で使用することができます。
|
||||
* これらのスキーマは、生成されたOpenAPIスキーマの一部となり、自動ドキュメントの<abbr title = "User Interfaces">UI</abbr>に使用されます。
|
||||
* データが無効な場合は、どこで何が不正なデータだったのかを正確に示す、分かりやすい明確なエラーを返します。
|
||||
* 受け取ったデータをパラメータ `item` に渡します。
|
||||
* 関数内で `Item` 型として宣言したため、すべての属性とその型について、エディタサポート(補完など)も利用できます。
|
||||
* モデル向けの <a href="https://json-schema.org" class="external-link" target="_blank">JSON Schema</a> 定義を生成します。プロジェクトにとって意味があるなら、他の場所でも好きなように利用できます。
|
||||
* それらのスキーマは生成されるOpenAPIスキーマの一部となり、自動ドキュメントの <abbr title="User Interfaces">UIs</abbr> で使用されます。
|
||||
|
||||
## 自動ドキュメント生成
|
||||
## 自動ドキュメント { #automatic-docs }
|
||||
|
||||
モデルのJSONスキーマはOpenAPIで生成されたスキーマの一部になり、対話的なAPIドキュメントに表示されます:
|
||||
モデルのJSON Schemaは、OpenAPIで生成されたスキーマの一部になり、対話的なAPIドキュメントに表示されます:
|
||||
|
||||
<img src="/img/tutorial/body/image01.png">
|
||||
|
||||
そして、それらが使われる *パスオペレーション* のそれぞれのAPIドキュメントにも表示されます:
|
||||
また、それらが必要な各 *path operation* 内のAPIドキュメントでも使用されます:
|
||||
|
||||
<img src="/img/tutorial/body/image02.png">
|
||||
|
||||
## エディターサポート
|
||||
## エディタサポート { #editor-support }
|
||||
|
||||
エディターによる型ヒントと補完が関数内で利用できます (Pydanticモデルではなく `dict` を受け取ると、同じサポートは受けられません):
|
||||
エディタ上で、関数内のあらゆる場所で型ヒントと補完が得られます(Pydanticモデルの代わりに `dict` を受け取った場合は起きません):
|
||||
|
||||
<img src="/img/tutorial/body/image03.png">
|
||||
|
||||
型によるエラーチェックも可能です:
|
||||
不正な型操作に対するエラーチェックも得られます:
|
||||
|
||||
<img src="/img/tutorial/body/image04.png">
|
||||
|
||||
これは偶然ではなく、このデザインに基づいてフレームワークが作られています。
|
||||
これは偶然ではなく、フレームワーク全体がその設計を中心に構築されています。
|
||||
|
||||
全てのエディターで機能することを確認するために、実装前の設計時に徹底的にテストしました。
|
||||
そして、すべてのエディタで動作することを確実にするために、実装前の設計フェーズで徹底的にテストされました。
|
||||
|
||||
これをサポートするためにPydantic自体にもいくつかの変更がありました。
|
||||
これをサポートするために、Pydantic自体にもいくつかの変更が加えられました。
|
||||
|
||||
上記のスクリーンショットは<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> で撮影されたものです。
|
||||
|
||||
しかし、<a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>やほとんどのPythonエディタでも同様なエディターサポートを受けられます:
|
||||
ただし、<a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> や、他のほとんどのPythonエディタでも同じエディタサポートを得られます:
|
||||
|
||||
<img src="/img/tutorial/body/image05.png">
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
<a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a>エディタを使用している場合は、<a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a>が使用可能です。
|
||||
エディタとして <a href="https://www.jetbrains.com/pycharm/" class="external-link" target="_blank">PyCharm</a> を使用している場合、<a href="https://github.com/koxudaxi/pydantic-pycharm-plugin/" class="external-link" target="_blank">Pydantic PyCharm Plugin</a> を使用できます。
|
||||
|
||||
以下のエディターサポートが強化されます:
|
||||
以下により、Pydanticモデルに対するエディタサポートが改善されます:
|
||||
|
||||
* 自動補完
|
||||
* 型チェック
|
||||
* リファクタリング
|
||||
* 検索
|
||||
* インスペクション
|
||||
* auto-completion
|
||||
* type checks
|
||||
* refactoring
|
||||
* searching
|
||||
* inspections
|
||||
|
||||
///
|
||||
|
||||
## モデルの使用
|
||||
## モデルを使用する { #use-the-model }
|
||||
|
||||
関数内部で、モデルの全ての属性に直接アクセスできます:
|
||||
関数内では、モデルオブジェクトのすべての属性に直接アクセスできます:
|
||||
|
||||
{* ../../docs_src/body/tutorial002.py hl[21] *}
|
||||
{* ../../docs_src/body/tutorial002_py310.py *}
|
||||
|
||||
## リクエストボディ + パスパラメータ
|
||||
## リクエストボディ + パスパラメータ { #request-body-path-parameters }
|
||||
|
||||
パスパラメータとリクエストボディを同時に宣言できます。
|
||||
|
||||
**FastAPI** はパスパラメータである関数パラメータは**パスから受け取り**、Pydanticモデルによって宣言された関数パラメータは**リクエストボディから受け取る**ということを認識します。
|
||||
**FastAPI** は、パスパラメータに一致する関数パラメータは **パスから取得** し、Pydanticモデルとして宣言された関数パラメータは **リクエストボディから取得** すべきだと認識します。
|
||||
|
||||
{* ../../docs_src/body/tutorial003.py hl[17:18] *}
|
||||
{* ../../docs_src/body/tutorial003_py310.py hl[15:16] *}
|
||||
|
||||
## リクエストボディ + パスパラメータ + クエリパラメータ
|
||||
|
||||
また、**ボディ**と**パス**と**クエリ**のパラメータも同時に宣言できます。
|
||||
## リクエストボディ + パス + クエリパラメータ { #request-body-path-query-parameters }
|
||||
|
||||
**FastAPI** はそれぞれを認識し、適切な場所からデータを取得します。
|
||||
**body**、**path**、**query** パラメータもすべて同時に宣言できます。
|
||||
|
||||
{* ../../docs_src/body/tutorial004.py hl[18] *}
|
||||
**FastAPI** はそれぞれを認識し、正しい場所からデータを取得します。
|
||||
|
||||
関数パラメータは以下の様に認識されます:
|
||||
{* ../../docs_src/body/tutorial004_py310.py hl[16] *}
|
||||
|
||||
* パラメータが**パス**で宣言されている場合は、優先的にパスパラメータとして扱われます。
|
||||
* パラメータが**単数型** (`int`、`float`、`str`、`bool` など)の場合は**クエリ**パラメータとして解釈されます。
|
||||
* パラメータが **Pydantic モデル**型で宣言された場合、リクエスト**ボディ**として解釈されます。
|
||||
関数パラメータは以下のように認識されます:
|
||||
|
||||
* パラメータが **path** でも宣言されている場合、パスパラメータとして使用されます。
|
||||
* パラメータが **単数型**(`int`、`float`、`str`、`bool` など)の場合、**query** パラメータとして解釈されます。
|
||||
* パラメータが **Pydanticモデル** の型として宣言されている場合、リクエスト **body** として解釈されます。
|
||||
|
||||
/// note | 備考
|
||||
|
||||
FastAPIは、`= None`があるおかげで、`q`がオプショナルだとわかります。
|
||||
FastAPIは、デフォルト値 `= None` があるため、`q` の値が必須ではないことを認識します。
|
||||
|
||||
`Optional[str]` の`Optional` はFastAPIでは使用されていません(FastAPIは`str`の部分のみ使用します)。しかし、`Optional[str]` はエディタがコードのエラーを見つけるのを助けてくれます。
|
||||
`str | None`(Python 3.10+)や `Union[str, None]`(Python 3.9+)の `Union` は、値が必須ではないことを判断するためにFastAPIでは使用されません。`= None` というデフォルト値があるため、必須ではないことを認識します。
|
||||
|
||||
しかし、型アノテーションを追加すると、エディタがより良いサポートを提供し、エラーを検出できるようになります。
|
||||
|
||||
///
|
||||
|
||||
## Pydanticを使わない方法
|
||||
## Pydanticを使わない方法 { #without-pydantic }
|
||||
|
||||
もしPydanticモデルを使用したくない場合は、**Body**パラメータが利用できます。[Body - Multiple Parameters: Singular values in body](body-multiple-params.md#_2){.internal-link target=_blank}を確認してください。
|
||||
Pydanticモデルを使いたくない場合は、**Body** パラメータも使用できます。[Body - Multiple Parameters: Singular values in body](body-multiple-params.md#singular-values-in-body){.internal-link target=_blank} のドキュメントを参照してください。
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# クッキーパラメータモデル
|
||||
# クッキーパラメータモデル { #cookie-parameter-models }
|
||||
|
||||
もし関連する**複数のクッキー**から成るグループがあるなら、それらを宣言するために、**Pydanticモデル**を作成できます。🍪
|
||||
|
||||
こうすることで、**複数の場所**で**そのPydanticモデルを再利用**でき、バリデーションやメタデータを、すべてのクッキーパラメータに対して一度に宣言できます。😎
|
||||
こうすることで、**複数の場所**で**そのPydanticモデルを再利用**でき、バリデーションやメタデータを、すべてのパラメータに対して一度に宣言できます。😎
|
||||
|
||||
/// note | 備考
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
|
||||
///
|
||||
|
||||
## クッキーにPydanticモデルを使用する
|
||||
## Pydanticモデルを使用したクッキー { #cookies-with-a-pydantic-model }
|
||||
|
||||
必要な複数の**クッキー**パラメータを**Pydanticモデル**で宣言し、さらに、それを `Cookie` として宣言しましょう:
|
||||
必要な複数の**クッキー**パラメータを**Pydanticモデル**で宣言し、さらに、パラメータを `Cookie` として宣言しましょう:
|
||||
|
||||
{* ../../docs_src/cookie_param_models/tutorial001_an_py310.py hl[9:12,16] *}
|
||||
|
||||
**FastAPI**は、リクエストの**クッキー**から**それぞれのフィールド**のデータを**抽出**し、定義された**Pydanticモデル**を提供します。
|
||||
**FastAPI**は、リクエストで受け取った**クッキー**から**それぞれのフィールド**のデータを**抽出**し、定義したPydanticモデルを提供します。
|
||||
|
||||
## ドキュメントの確認
|
||||
## ドキュメントの確認 { #check-the-docs }
|
||||
|
||||
対話的APIドキュメントUI `/docs` で、定義されているクッキーを確認できます:
|
||||
|
||||
@@ -32,18 +32,17 @@
|
||||
<img src="/img/tutorial/cookie-param-models/image01.png">
|
||||
</div>
|
||||
|
||||
/// info | 備考
|
||||
|
||||
/// info | 情報
|
||||
|
||||
**ブラウザがクッキーを処理し**ていますが、特別な方法で内部的に処理を行っているために、**JavaScript**からは簡単に操作**できない**ことに留意してください。
|
||||
|
||||
**対話的APIドキュメントUI** `/docs` にアクセスすれば、*パスオペレーション*に関するクッキーの**ドキュメンテーション**を確認できます。
|
||||
**APIドキュメントUI** `/docs` にアクセスすれば、*path operation*に関するクッキーの**ドキュメンテーション**を確認できます。
|
||||
|
||||
しかし、たとえ**クッキーデータを入力して**「Execute」をクリックしても、対話的APIドキュメントUIは**JavaScript**で動作しているためクッキーは送信されず、まるで値を入力しなかったかのような**エラー**メッセージが表示されます。
|
||||
しかし、たとえ**データを入力して**「Execute」をクリックしても、ドキュメントUIは**JavaScript**で動作しているためクッキーは送信されず、まるで値を入力しなかったかのような**エラー**メッセージが表示されます。
|
||||
|
||||
///
|
||||
|
||||
## 余分なクッキーを禁止する
|
||||
## 余分なクッキーを禁止する { #forbid-extra-cookies }
|
||||
|
||||
特定の(あまり一般的ではないかもしれない)ケースで、受け付けるクッキーを**制限**する必要があるかもしれません。
|
||||
|
||||
@@ -51,7 +50,7 @@
|
||||
|
||||
Pydanticのモデルの Configuration を利用して、 `extra` フィールドを `forbid` とすることができます。
|
||||
|
||||
{* ../../docs_src/cookie_param_models/tutorial002_an_py39.py hl[10] *}
|
||||
{* ../../docs_src/cookie_param_models/tutorial002_an_py310.py hl[10] *}
|
||||
|
||||
もしクライアントが**余分なクッキー**を送ろうとすると、**エラー**レスポンスが返されます。
|
||||
|
||||
@@ -72,6 +71,6 @@ Pydanticのモデルの Configuration を利用して、 `extra` フィールド
|
||||
}
|
||||
```
|
||||
|
||||
## まとめ
|
||||
## まとめ { #summary }
|
||||
|
||||
**FastAPI**では、<abbr title="帰ってしまう前に最後のクッキーをどうぞ。🍪 (原文: Have a last cookie before you go. 🍪)">**クッキー**</abbr>を宣言するために、**Pydanticモデル**を使用できます。😎
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
# クッキーのパラメータ
|
||||
# クッキーのパラメータ { #cookie-parameters }
|
||||
|
||||
クッキーのパラメータは、`Query`や`Path`のパラメータを定義するのと同じ方法で定義できます。
|
||||
|
||||
## `Cookie`をインポート
|
||||
## `Cookie`をインポート { #import-cookie }
|
||||
|
||||
まず、`Cookie`をインポートします:
|
||||
|
||||
{* ../../docs_src/cookie_params/tutorial001.py hl[3] *}
|
||||
{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[3] *}
|
||||
|
||||
## `Cookie`のパラメータを宣言
|
||||
## `Cookie`のパラメータを宣言 { #declare-cookie-parameters }
|
||||
|
||||
次に、`Path`や`Query`と同じ構造を使ってクッキーのパラメータを宣言します。
|
||||
|
||||
最初の値がデフォルト値で、追加の検証パラメータや注釈パラメータをすべて渡すことができます:
|
||||
|
||||
{* ../../docs_src/cookie_params/tutorial001.py hl[9] *}
|
||||
{* ../../docs_src/cookie_params/tutorial001_an_py310.py hl[9] *}
|
||||
|
||||
/// note | 技術詳細
|
||||
|
||||
@@ -30,6 +30,16 @@
|
||||
|
||||
///
|
||||
|
||||
## まとめ
|
||||
/// info | 情報
|
||||
|
||||
クッキーは`Cookie`を使って宣言し、`Query`や`Path`と同じパターンを使用する。
|
||||
**ブラウザがクッキーを**特殊な方法で裏側で扱うため、**JavaScript** から簡単には触れられないことを念頭に置いてください。
|
||||
|
||||
`/docs` の **API docs UI** に移動すると、*path operation* のクッキーに関する **documentation** を確認できます。
|
||||
|
||||
しかし、データを **入力** して「Execute」をクリックしても、docs UI は **JavaScript** で動作するためクッキーは送信されず、値を何も書かなかったかのような **error** メッセージが表示されます。
|
||||
|
||||
///
|
||||
|
||||
## まとめ { #recap }
|
||||
|
||||
クッキーは`Cookie`を使って宣言し、`Query`や`Path`と同じ共通のパターンを使用する。
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# CORS (オリジン間リソース共有)
|
||||
# CORS (Cross-Origin Resource Sharing) { #cors-cross-origin-resource-sharing }
|
||||
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">CORSまたは「オリジン間リソース共有」</a> は、ブラウザで実行されているフロントエンドにバックエンドと通信するJavaScriptコードがあり、そのバックエンドがフロントエンドとは異なる「オリジン」にある状況を指します。
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">CORSまたは「Cross-Origin Resource Sharing」</a> は、ブラウザで実行されているフロントエンドにバックエンドと通信するJavaScriptコードがあり、そのバックエンドがフロントエンドとは異なる「オリジン」にある状況を指します。
|
||||
|
||||
## オリジン
|
||||
## オリジン { #origin }
|
||||
|
||||
オリジンはプロトコル (`http`、`https`) とドメイン (`myapp.com`、`localhost`、`localhost.tiangolo.com`) とポート (`80`、`443`、`8080`) の組み合わせです。
|
||||
|
||||
@@ -14,25 +14,25 @@
|
||||
|
||||
すべて `localhost` であっても、異なるプロトコルやポートを使用するので、異なる「オリジン」です。
|
||||
|
||||
## ステップ
|
||||
## ステップ { #steps }
|
||||
|
||||
そして、ブラウザ上で実行されているフロントエンド (`http://localhost:8080`) があり、そのJavaScriptが `http://localhost` で実行されているバックエンドと通信するとします。(ポートを指定していないので、ブラウザはデフォルトの`80`ポートを使用します)
|
||||
|
||||
次に、ブラウザはHTTPの `OPTIONS` リクエストをバックエンドに送信します。そして、バックエンドがこの異なるオリジン (`http://localhost:8080`) からの通信を許可する適切なヘッダーを送信すると、ブラウザはフロントエンドのJavaScriptにバックエンドへのリクエストを送信させます。
|
||||
次に、ブラウザはHTTPの `OPTIONS` リクエストを `:80` のバックエンドに送信します。そして、バックエンドがこの異なるオリジン (`http://localhost:8080`) からの通信を許可する適切なヘッダーを送信すると、`:8080` のブラウザはフロントエンドのJavaScriptに `:80` のバックエンドへのリクエストを送信させます。
|
||||
|
||||
これを実現するには、バックエンドに「許可されたオリジン」のリストがなければなりません。
|
||||
これを実現するには、`:80` のバックエンドに「許可されたオリジン」のリストがなければなりません。
|
||||
|
||||
この場合、フロントエンドを正しく機能させるには、そのリストに `http://localhost:8080` を含める必要があります。
|
||||
この場合、`:8080` のフロントエンドを正しく機能させるには、そのリストに `http://localhost:8080` を含める必要があります。
|
||||
|
||||
## ワイルドカード
|
||||
## ワイルドカード { #wildcards }
|
||||
|
||||
リストを `"*"` (ワイルドカード) と宣言して、すべてを許可することもできます。
|
||||
リストを `"*"` (「ワイルドカード」) と宣言して、すべてを許可することもできます。
|
||||
|
||||
ただし、Bearer Tokenで使用されるような認証ヘッダーやCookieなどのクレデンシャル情報に関するものを除いて、特定の種類の通信のみが許可されます。
|
||||
ただし、クレデンシャル情報に関するもの、つまりCookie、Bearer Tokenで使用されるようなAuthorizationヘッダーなどを含むものは除外され、特定の種類の通信のみが許可されます。
|
||||
|
||||
したがって、すべてを正しく機能させるために、許可されたオリジンの明示的な指定をお勧めします。
|
||||
|
||||
## `CORSMiddleware` の使用
|
||||
## `CORSMiddleware` の使用 { #use-corsmiddleware }
|
||||
|
||||
**FastAPI** アプリケーションでは `CORSMiddleware` を使用して、CORSに関する設定ができます。
|
||||
|
||||
@@ -42,39 +42,43 @@
|
||||
|
||||
以下も、バックエンドに許可させるかどうか指定できます:
|
||||
|
||||
* クレデンシャル情報 (認証ヘッダー、Cookieなど) 。
|
||||
* クレデンシャル情報 (Authorizationヘッダー、Cookieなど) 。
|
||||
* 特定のHTTPメソッド (`POST`、`PUT`) またはワイルドカード `"*"` を使用してすべて許可。
|
||||
* 特定のHTTPヘッダー、またはワイルドカード `"*"`を使用してすべて許可。
|
||||
|
||||
{* ../../docs_src/cors/tutorial001.py hl[2,6:11,13:19] *}
|
||||
{* ../../docs_src/cors/tutorial001_py39.py hl[2,6:11,13:19] *}
|
||||
|
||||
`CORSMiddleware` 実装のデフォルトのパラメータはCORSに関して制限を与えるものになっているので、ブラウザにドメインを跨いで特定のオリジン、メソッド、またはヘッダーを使用可能にするためには、それらを明示的に有効にする必要があります
|
||||
|
||||
`CORSMiddleware` 実装で使用されるデフォルトのパラメータはデフォルトで制限が厳しいため、ブラウザがクロスドメインのコンテキストでそれらを使用できるようにするには、特定のオリジン、メソッド、またはヘッダーを明示的に有効にする必要があります。
|
||||
|
||||
以下の引数がサポートされています:
|
||||
|
||||
* `allow_origins` - オリジン間リクエストを許可するオリジンのリスト。例えば、`['https://example.org', 'https://www.example.org']`。`['*']`を使用して任意のオリジンを許可できます。
|
||||
* `allow_origin_regex` - オリジン間リクエストを許可するオリジンの正規表現文字列。例えば、`'https://.*\.example\.org'`。
|
||||
* `allow_methods` - オリジン間リクエストで許可するHTTPメソッドのリスト。デフォルトは `['GET']` です。`['*']`を使用してすべての標準メソッドを許可できます。
|
||||
* `allow_headers` - オリジン間リクエストでサポートするHTTPリクエストヘッダーのリスト。デフォルトは `[]` です。`['*']`を使用して、すべてのヘッダーを許可できます。CORSリクエストでは、 `Accept` 、 `Accept-Language` 、 `Content-Language` 、 `Content-Type` ヘッダーが常に許可されます。
|
||||
* `allow_headers` - オリジン間リクエストでサポートするHTTPリクエストヘッダーのリスト。デフォルトは `[]` です。`['*']`を使用して、すべてのヘッダーを許可できます。<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests" class="external-link" rel="noopener" target="_blank">シンプルなCORSリクエスト</a>では、 `Accept` 、 `Accept-Language` 、 `Content-Language` 、 `Content-Type` ヘッダーが常に許可されます。
|
||||
* `allow_credentials` - オリジン間リクエストでCookieをサポートする必要があることを示します。デフォルトは `False` です。
|
||||
|
||||
`allow_credentials` が `True` に設定されている場合、`allow_origins`、`allow_methods`、`allow_headers` のいずれも `['*']` に設定できません。これらはすべて<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#credentialed_requests_and_wildcards" class="external-link" rel="noopener" target="_blank">明示的に指定</a>する必要があります。
|
||||
|
||||
* `expose_headers` - ブラウザからアクセスできるようにするレスポンスヘッダーを示します。デフォルトは `[]` です。
|
||||
* `max_age` - ブラウザがCORSレスポンスをキャッシュする最大時間を秒単位で設定します。デフォルトは `600` です。
|
||||
|
||||
このミドルウェアは2種類のHTTPリクエストに応答します...
|
||||
|
||||
### CORSプリフライトリクエスト
|
||||
### CORSプリフライトリクエスト { #cors-preflight-requests }
|
||||
|
||||
これらは、 `Origin` ヘッダーと `Access-Control-Request-Method` ヘッダーを持つ `OPTIONS` リクエストです。
|
||||
|
||||
この場合、ミドルウェアはリクエストを横取りし、適切なCORSヘッダーと共に情報提供のために `200` または `400` のレスポンスを返します。
|
||||
|
||||
### シンプルなリクエスト
|
||||
### シンプルなリクエスト { #simple-requests }
|
||||
|
||||
`Origin` ヘッダーのあるリクエスト。この場合、ミドルウェアは通常どおりリクエストに何もしないですが、レスポンスに適切なCORSヘッダーを加えます。
|
||||
|
||||
## より詳しい情報
|
||||
## より詳しい情報 { #more-info }
|
||||
|
||||
<abbr title="Cross-Origin Resource Sharing (オリジン間リソース共有)">CORS</abbr>についてより詳しい情報は、<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">Mozilla CORS documentation</a> を参照して下さい。
|
||||
<abbr title="Cross-Origin Resource Sharing – オリジン間リソース共有">CORS</abbr>についてより詳しい情報は、<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" class="external-link" target="_blank">Mozilla CORS documentation</a> を参照して下さい。
|
||||
|
||||
/// note | 技術詳細
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# デバッグ
|
||||
# デバッグ { #debugging }
|
||||
|
||||
Visual Studio CodeやPyCharmなどを使用して、エディター上でデバッガーと連携できます。
|
||||
|
||||
## `uvicorn` の実行
|
||||
## `uvicorn` を呼び出す { #call-uvicorn }
|
||||
|
||||
FastAPIアプリケーション上で、`uvicorn` を直接インポートして実行します:
|
||||
|
||||
{* ../../docs_src/debugging/tutorial001.py hl[1,15] *}
|
||||
{* ../../docs_src/debugging/tutorial001_py39.py hl[1,15] *}
|
||||
|
||||
### `__name__ == "__main__"` について
|
||||
### `__name__ == "__main__"` について { #about-name-main }
|
||||
|
||||
`__name__ == "__main__"` の主な目的は、ファイルが次のコマンドで呼び出されたときに実行されるコードを用意することです:
|
||||
|
||||
@@ -26,7 +26,7 @@ $ python myapp.py
|
||||
from myapp import app
|
||||
```
|
||||
|
||||
#### より詳しい説明
|
||||
#### より詳しい説明 { #more-details }
|
||||
|
||||
ファイルの名前が `myapp.py` だとします。
|
||||
|
||||
@@ -62,7 +62,7 @@ from myapp import app
|
||||
# Some more code
|
||||
```
|
||||
|
||||
`myapp.py` 内の自動変数には、値が `"__main __"` の変数 `__name__` はありません。
|
||||
その場合、`myapp.py` 内の自動的に作成された変数 `__name__` は、値として `"__main__"` を持ちません。
|
||||
|
||||
したがって、以下の行:
|
||||
|
||||
@@ -78,7 +78,7 @@ from myapp import app
|
||||
|
||||
///
|
||||
|
||||
## デバッガーでコードを実行
|
||||
## デバッガーでコードを実行 { #run-your-code-with-your-debugger }
|
||||
|
||||
コードから直接Uvicornサーバーを実行しているため、デバッガーから直接Pythonプログラム (FastAPIアプリケーション) を呼び出せます。
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# 依存関係としてのクラス
|
||||
# 依存関係としてのクラス { #classes-as-dependencies }
|
||||
|
||||
**依存性注入** システムを深く掘り下げる前に、先ほどの例をアップグレードしてみましょう。
|
||||
|
||||
## 前の例の`dict`
|
||||
## 前の例の`dict` { #a-dict-from-the-previous-example }
|
||||
|
||||
前の例では、依存関係("dependable")から`dict`を返していました:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial001.py hl[9] *}
|
||||
{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[9] *}
|
||||
|
||||
しかし、*path operation関数*のパラメータ`commons`に`dict`が含まれています。
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
もっとうまくやれるはずです...。
|
||||
|
||||
## 依存関係を作るもの
|
||||
## 依存関係を作るもの { #what-makes-a-dependency }
|
||||
|
||||
これまでは、依存関係が関数として宣言されているのを見てきました。
|
||||
|
||||
@@ -38,7 +38,7 @@ something(some_argument, some_keyword_argument="foo")
|
||||
|
||||
これを「呼び出し可能」なものと呼びます。
|
||||
|
||||
## 依存関係としてのクラス
|
||||
## 依存関係としてのクラス { #classes-as-dependencies_1 }
|
||||
|
||||
Pythonのクラスのインスタンスを作成する際に、同じ構文を使用していることに気づくかもしれません。
|
||||
|
||||
@@ -67,48 +67,66 @@ FastAPIが実際にチェックしているのは、それが「呼び出し可
|
||||
|
||||
それは、パラメータが全くない呼び出し可能なものにも適用されます。パラメータのない*path operation関数*と同じように。
|
||||
|
||||
そこで、上で紹介した依存関係の`common_parameters`を`CommonQueryParams`クラスに変更します:
|
||||
そこで、上で紹介した依存関係の"dependable" `common_parameters`を`CommonQueryParams`クラスに変更します:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial002.py hl[11,12,13,14,15] *}
|
||||
{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[11:15] *}
|
||||
|
||||
クラスのインスタンスを作成するために使用される`__init__`メソッドに注目してください:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial002.py hl[12] *}
|
||||
{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[12] *}
|
||||
|
||||
...以前の`common_parameters`と同じパラメータを持っています:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial001.py hl[8] *}
|
||||
{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8] *}
|
||||
|
||||
これらのパラメータは **FastAPI** が依存関係を「解決」するために使用するものです。
|
||||
|
||||
どちらの場合も以下を持っています:
|
||||
|
||||
* オプショナルの`q`クエリパラメータ。
|
||||
* `skip`クエリパラメータ、デフォルトは`0`。
|
||||
* `limit`クエリパラメータ、デフォルトは`100`。
|
||||
* `str`であるオプショナルの`q`クエリパラメータ。
|
||||
* デフォルトが`0`である`int`の`skip`クエリパラメータ。
|
||||
* デフォルトが`100`である`int`の`limit`クエリパラメータ。
|
||||
|
||||
どちらの場合も、データは変換され、検証され、OpenAPIスキーマなどで文書化されます。
|
||||
|
||||
## 使用
|
||||
## 使用 { #use-it }
|
||||
|
||||
これで、このクラスを使用して依存関係を宣言することができます。
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial002.py hl[19] *}
|
||||
{* ../../docs_src/dependencies/tutorial002_an_py310.py hl[19] *}
|
||||
|
||||
**FastAPI** は`CommonQueryParams`クラスを呼び出します。これにより、そのクラスの「インスタンス」が作成され、インスタンスはパラメータ`commons`として関数に渡されます。
|
||||
|
||||
## 型注釈と`Depends`
|
||||
## 型注釈と`Depends` { #type-annotation-vs-depends }
|
||||
|
||||
上のコードでは`CommonQueryParams`を2回書いていることに注目してください:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ 注釈なし
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
可能であれば`Annotated`バージョンを使用することを推奨します。
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
以下にある最後の`CommonQueryParams`:
|
||||
|
||||
```Python
|
||||
... = Depends(CommonQueryParams)
|
||||
... Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
...は、**FastAPI** が依存関係を知るために実際に使用するものです。
|
||||
@@ -119,55 +137,145 @@ commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
|
||||
この場合、以下にある最初の`CommonQueryParams`:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, ...
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ 注釈なし
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
可能であれば`Annotated`バージョンを使用することを推奨します。
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams ...
|
||||
```
|
||||
|
||||
...は **FastAPI** に対して特別な意味をもちません。FastAPIはデータ変換や検証などには使用しません(それらのためには`= Depends(CommonQueryParams)`を使用しています)。
|
||||
////
|
||||
|
||||
...は **FastAPI** に対して特別な意味をもちません。FastAPIはデータ変換や検証などには使用しません(それらのためには`Depends(CommonQueryParams)`を使用しています)。
|
||||
|
||||
実際には以下のように書けばいいだけです:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
commons: Annotated[Any, Depends(CommonQueryParams)]
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ 注釈なし
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
可能であれば`Annotated`バージョンを使用することを推奨します。
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
以下にあるように:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial003.py hl[19] *}
|
||||
{* ../../docs_src/dependencies/tutorial003_an_py310.py hl[19] *}
|
||||
|
||||
しかし、型を宣言することは推奨されています。そうすれば、エディタは`commons`のパラメータとして何が渡されるかを知ることができ、コードの補完や型チェックなどを行うのに役立ちます:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/dependencies/image02.png">
|
||||
<img src="/img/tutorial/dependencies/image02.png">
|
||||
|
||||
## ショートカット
|
||||
## ショートカット { #shortcut }
|
||||
|
||||
しかし、ここでは`CommonQueryParams`を2回書くというコードの繰り返しが発生していることがわかります:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ 注釈なし
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
可能であれば`Annotated`バージョンを使用することを推奨します。
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
依存関係が、クラス自体のインスタンスを作成するために**FastAPI**が「呼び出す」*特定の*クラスである場合、**FastAPI** はこれらのケースのショートカットを提供しています。
|
||||
|
||||
それらの具体的なケースについては以下のようにします:
|
||||
|
||||
以下のように書く代わりに:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends(CommonQueryParams)]
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ 注釈なし
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
可能であれば`Annotated`バージョンを使用することを推奨します。
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends(CommonQueryParams)
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
...以下のように書きます:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python
|
||||
commons: Annotated[CommonQueryParams, Depends()]
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ 注釈なし
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
可能であれば`Annotated`バージョンを使用することを推奨します。
|
||||
|
||||
///
|
||||
|
||||
```Python
|
||||
commons: CommonQueryParams = Depends()
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
パラメータの型として依存関係を宣言し、`Depends()`の中でパラメータを指定せず、`Depends()`をその関数のパラメータの「デフォルト」値(`=`のあとの値)として使用することで、`Depends(CommonQueryParams)`の中でクラス全体を*もう一度*書かなくてもよくなります。
|
||||
|
||||
同じ例では以下のようになります:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial004.py hl[19] *}
|
||||
{* ../../docs_src/dependencies/tutorial004_an_py310.py hl[19] *}
|
||||
|
||||
...そして **FastAPI** は何をすべきか知っています。
|
||||
|
||||
|
||||
@@ -1,57 +1,69 @@
|
||||
# path operationデコレータの依存関係
|
||||
# path operation デコレータの依存関係 { #dependencies-in-path-operation-decorators }
|
||||
|
||||
場合によっては*path operation関数*の中で依存関係の戻り値を本当に必要としないこともあります。
|
||||
場合によっては、*path operation 関数*の中で依存関係の戻り値を実際には必要としないことがあります。
|
||||
|
||||
もしくは、依存関係が値を返さない場合もあります。
|
||||
または、依存関係が値を返さない場合もあります。
|
||||
|
||||
しかし、それでも実行・解決する必要があります。
|
||||
しかし、それでも実行・解決される必要があります。
|
||||
|
||||
このような場合、*path operation関数*のパラメータを`Depends`で宣言する代わりに、*path operation decorator*に`dependencies`の`list`を追加することができます。
|
||||
そのような場合、`Depends` で *path operation 関数* のパラメータを宣言する代わりに、*path operation デコレータ*に `dependencies` の `list` を追加できます。
|
||||
|
||||
## *path operationデコレータ*への`dependencies`の追加
|
||||
## *path operation デコレータ*に`dependencies`を追加 { #add-dependencies-to-the-path-operation-decorator }
|
||||
|
||||
*path operationデコレータ*はオプショナルの引数`dependencies`を受け取ります。
|
||||
*path operation デコレータ*はオプション引数`dependencies`を受け取ります。
|
||||
|
||||
それは`Depends()`の`list`であるべきです:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006.py hl[17] *}
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[19] *}
|
||||
|
||||
これらの依存関係は、通常の依存関係と同様に実行・解決されます。しかし、それらの値(何かを返す場合)は*path operation関数*には渡されません。
|
||||
これらの依存関係は、通常の依存関係と同様に実行・解決されます。しかし、それらの値(何かを返す場合)は*path operation 関数*には渡されません。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
エディタによっては、未使用の関数パラメータをチェックしてエラーとして表示するものもあります。
|
||||
一部のエディタは、未使用の関数パラメータをチェックしてエラーとして表示します。
|
||||
|
||||
`dependencies`を`path operationデコレータ`で使用することで、エディタやツールのエラーを回避しながら確実に実行することができます。
|
||||
これらの`dependencies`を*path operation デコレータ*で使用することで、エディタ/ツールのエラーを回避しつつ、確実に実行されるようにできます。
|
||||
|
||||
また、コードの未使用のパラメータがあるのを見て、それが不要だと思ってしまうような新しい開発者の混乱を避けるのにも役立つかもしれません。
|
||||
また、コード内の未使用のパラメータを見た新しい開発者が、それを不要だと思って混乱するのを避ける助けにもなるかもしれません。
|
||||
|
||||
///
|
||||
|
||||
## 依存関係のエラーと戻り値
|
||||
/// info | 情報
|
||||
|
||||
通常使用している依存関係の*関数*と同じものを使用することができます。
|
||||
この例では、架空のカスタムヘッダー `X-Key` と `X-Token` を使用しています。
|
||||
|
||||
### 依存関係の要件
|
||||
しかし実際のケースでセキュリティを実装する際は、統合された[Security utilities(次の章)](../security/index.md){.internal-link target=_blank}を使うことで、より多くの利点を得られます。
|
||||
|
||||
これらはリクエストの要件(ヘッダのようなもの)やその他のサブ依存関係を宣言することができます:
|
||||
///
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006.py hl[6,11] *}
|
||||
## 依存関係のエラーと戻り値 { #dependencies-errors-and-return-values }
|
||||
|
||||
### 例外の発生
|
||||
通常使用している依存関係の*関数*と同じものを使用できます。
|
||||
|
||||
これらの依存関係は通常の依存関係と同じように、例外を`raise`発生させることができます:
|
||||
### 依存関係の要件 { #dependency-requirements }
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006.py hl[8,13] *}
|
||||
これらはリクエストの要件(ヘッダーのようなもの)やその他のサブ依存関係を宣言できます:
|
||||
|
||||
### 戻り値
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[8,13] *}
|
||||
|
||||
### 例外の発生 { #raise-exceptions }
|
||||
|
||||
これらの依存関係は、通常の依存関係と同じように例外を`raise`できます:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[10,15] *}
|
||||
|
||||
### 戻り値 { #return-values }
|
||||
|
||||
そして、値を返すことも返さないこともできますが、値は使われません。
|
||||
|
||||
つまり、すでにどこかで使っている通常の依存関係(値を返すもの)を再利用することができ、値は使われなくても依存関係は実行されます:
|
||||
つまり、すでにどこかで使っている通常の依存関係(値を返すもの)を再利用でき、値は使われなくても依存関係は実行されます:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial006.py hl[9,14] *}
|
||||
{* ../../docs_src/dependencies/tutorial006_an_py39.py hl[11,16] *}
|
||||
|
||||
## *path operations*のグループに対する依存関係
|
||||
## *path operation*のグループに対する依存関係 { #dependencies-for-a-group-of-path-operations }
|
||||
|
||||
後で、より大きなアプリケーションの構造([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank})について読む時に、おそらく複数のファイルを使用して、*path operations*のグループに対して単一の`dependencies`パラメータを宣言する方法を学ぶでしょう。
|
||||
後で、より大きなアプリケーションを(おそらく複数ファイルで)構造化する方法([Bigger Applications - Multiple Files](../../tutorial/bigger-applications.md){.internal-link target=_blank})について読むときに、*path operation*のグループに対して単一の`dependencies`パラメータを宣言する方法を学びます。
|
||||
|
||||
## グローバル依存関係 { #global-dependencies }
|
||||
|
||||
次に、`FastAPI`アプリケーション全体に依存関係を追加して、各*path operation*に適用する方法を見ていきます。
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
# yieldを持つ依存関係
|
||||
# `yield`を持つ依存関係 { #dependencies-with-yield }
|
||||
|
||||
FastAPIは、いくつかの<abbr title='時々"exit"、"cleanup"、"teardown"、"close"、"context managers"、 ...のように呼ばれる'>終了後の追加のステップ</abbr>を行う依存関係をサポートしています。
|
||||
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>を行う依存関係をサポートしています。
|
||||
|
||||
これを行うには、`return`の代わりに`yield`を使い、その後に追加のステップを書きます。
|
||||
これを行うには、`return`の代わりに`yield`を使い、その後に追加のステップ(コード)を書きます。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
`yield`は必ず一度だけ使用するようにしてください。
|
||||
|
||||
///
|
||||
|
||||
/// info | 情報
|
||||
|
||||
これを動作させるには、**Python 3.7** 以上を使用するか、**Python 3.6** では"backports"をインストールする必要があります:
|
||||
|
||||
```
|
||||
pip install async-exit-stack async-generator
|
||||
```
|
||||
|
||||
これにより<a href="https://github.com/sorcio/async_exit_stack" class="external-link" target="_blank">async-exit-stack</a>と<a href="https://github.com/python-trio/async_generator" class="external-link" target="_blank">async-generator</a>がインストールされます。
|
||||
`yield`は必ず依存関係ごとに1回だけ使用するようにしてください。
|
||||
|
||||
///
|
||||
|
||||
@@ -35,21 +23,21 @@ pip install async-exit-stack async-generator
|
||||
|
||||
///
|
||||
|
||||
## `yield`を持つデータベースの依存関係
|
||||
## `yield`を持つデータベースの依存関係 { #a-database-dependency-with-yield }
|
||||
|
||||
例えば、これを使ってデータベースセッションを作成し、終了後にそれを閉じることができます。
|
||||
|
||||
レスポンスを送信する前に`yield`文を含む前のコードのみが実行されます。
|
||||
レスポンスを作成する前に、`yield`文より前のコード(および`yield`文を含む)が実行されます:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial007.py hl[2,3,4] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[2:4] *}
|
||||
|
||||
生成された値は、*path operations*や他の依存関係に注入されるものです:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial007.py hl[4] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[4] *}
|
||||
|
||||
`yield`文に続くコードは、レスポンスが送信された後に実行されます:
|
||||
`yield`文に続くコードは、レスポンスの後に実行されます:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial007.py hl[5,6] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[5:6] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
@@ -59,27 +47,27 @@ pip install async-exit-stack async-generator
|
||||
|
||||
///
|
||||
|
||||
## `yield`と`try`を持つ依存関係
|
||||
## `yield`と`try`を持つ依存関係 { #a-dependency-with-yield-and-try }
|
||||
|
||||
`yield`を持つ依存関係で`try`ブロックを使用した場合、その依存関係を使用した際に発生した例外を受け取ることになります。
|
||||
`yield`を持つ依存関係で`try`ブロックを使用した場合、その依存関係を使用した際にスローされたあらゆる例外を受け取ることになります。
|
||||
|
||||
例えば、途中のどこかの時点で、別の依存関係や*path operation*の中で、データベーストランザクションを「ロールバック」したり、その他のエラーを作成したりするコードがあった場合、依存関係の中で例外を受け取ることになります。
|
||||
例えば、途中のどこかの時点で、別の依存関係や*path operation*の中で、データベーストランザクションを「ロールバック」したり、その他の例外を作成したりするコードがあった場合、依存関係の中で例外を受け取ることになります。
|
||||
|
||||
そのため、依存関係の中にある特定の例外を`except SomeException`で探すことができます。
|
||||
|
||||
同様に、`finally`を用いて例外があったかどうかにかかわらず、終了ステップを確実に実行することができます。
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial007.py hl[3,5] *}
|
||||
{* ../../docs_src/dependencies/tutorial007_py39.py hl[3,5] *}
|
||||
|
||||
## `yield`を持つサブ依存関係
|
||||
## `yield`を持つサブ依存関係 { #sub-dependencies-with-yield }
|
||||
|
||||
任意の大きさや形のサブ依存関係やサブ依存関係の「ツリー」を持つことができ、その中で`yield`を使用することができます。
|
||||
|
||||
**FastAPI** は、`yield`を持つ各依存関係の「終了コード」が正しい順番で実行されていることを確認します。
|
||||
|
||||
例えば、`dependency_c`は`dependency_b`と`dependency_b`に依存する`dependency_a`に、依存することができます:
|
||||
例えば、`dependency_c`は`dependency_b`に、そして`dependency_b`は`dependency_a`に依存することができます:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008.py hl[4,12,20] *}
|
||||
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[6,14,22] *}
|
||||
|
||||
そして、それらはすべて`yield`を使用することができます。
|
||||
|
||||
@@ -87,11 +75,11 @@ pip install async-exit-stack async-generator
|
||||
|
||||
そして、`dependency_b`は`dependency_a`(ここでは`dep_a`という名前)の値を終了コードで利用できるようにする必要があります。
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008.py hl[16,17,24,25] *}
|
||||
{* ../../docs_src/dependencies/tutorial008_an_py39.py hl[18:19,26:27] *}
|
||||
|
||||
同様に、`yield`と`return`が混在した依存関係を持つこともできます。
|
||||
同様に、`yield`を持つ依存関係と`return`を持つ他の依存関係をいくつか持ち、それらの一部が他の一部に依存するようにもできます。
|
||||
|
||||
また、単一の依存関係を持っていて、`yield`などの他の依存関係をいくつか必要とすることもできます。
|
||||
また、単一の依存関係を持っていて、`yield`を持つ他の依存関係をいくつか必要とすることもできます。
|
||||
|
||||
依存関係の組み合わせは自由です。
|
||||
|
||||
@@ -105,32 +93,46 @@ pip install async-exit-stack async-generator
|
||||
|
||||
///
|
||||
|
||||
## `yield`と`HTTPException`を持つ依存関係
|
||||
## `yield`と`HTTPException`を持つ依存関係 { #dependencies-with-yield-and-httpexception }
|
||||
|
||||
`yield`と例外をキャッチする`try`ブロックを持つことができる依存関係を使用することができることがわかりました。
|
||||
`yield`を持つ依存関係を使い、何らかのコードを実行し、その後に`finally`の後で終了コードを実行しようとする`try`ブロックを持てることが分かりました。
|
||||
|
||||
`yield`の後の終了コードで`HTTPException`などを発生させたくなるかもしれません。しかし**それはうまくいきません**
|
||||
また、`except`を使って発生した例外をキャッチし、それに対して何かをすることもできます。
|
||||
|
||||
`yield`を持つ依存関係の終了コードは[例外ハンドラ](../handling-errors.md#_4){.internal-link target=_blank}の*後に*実行されます。依存関係によって投げられた例外を終了コード(`yield`の後)でキャッチするものはなにもありません。
|
||||
|
||||
つまり、`yield`の後に`HTTPException`を発生させた場合、`HTTTPException`をキャッチしてHTTP 400のレスポンスを返すデフォルトの(あるいは任意のカスタムの)例外ハンドラは、その例外をキャッチすることができなくなります。
|
||||
|
||||
これは、依存関係に設定されているもの(例えば、DBセッション)を、例えば、バックグラウンドタスクで使用できるようにするものです。
|
||||
|
||||
バックグラウンドタスクはレスポンスが送信された*後*に実行されます。そのため、*すでに送信されている*レスポンスを変更する方法すらないので、`HTTPException`を発生させる方法はありません。
|
||||
|
||||
しかし、バックグラウンドタスクがDBエラーを発生させた場合、少なくとも`yield`で依存関係のセッションをロールバックしたり、きれいに閉じたりすることができ、エラーをログに記録したり、リモートのトラッキングシステムに報告したりすることができます。
|
||||
|
||||
例外が発生する可能性があるコードがある場合は、最も普通の「Python流」なことをして、コードのその部分に`try`ブロックを追加してください。
|
||||
|
||||
レスポンスを返したり、レスポンスを変更したり、`HTTPException`を発生させたりする*前に*処理したいカスタム例外がある場合は、[カスタム例外ハンドラ](../handling-errors.md#_4){.internal-link target=_blank}を作成してください。
|
||||
例えば、`HTTPException`のように別の例外を発生させることができます。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
`HTTPException`を含む例外は、`yield`の*前*でも発生させることができます。ただし、後ではできません。
|
||||
これはやや高度なテクニックで、ほとんどの場合は本当に必要にはなりません。例えば、*path operation 関数*など、アプリケーションコードの他の場所から(`HTTPException`を含む)例外を発生させられるためです。
|
||||
|
||||
ただし必要であれば使えます。 🤓
|
||||
|
||||
///
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008b_an_py39.py hl[18:22,31] *}
|
||||
|
||||
例外をキャッチして、それに基づいてカスタムレスポンスを作成したい場合は、[カスタム例外ハンドラ](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}を作成してください。
|
||||
|
||||
## `yield`と`except`を持つ依存関係 { #dependencies-with-yield-and-except }
|
||||
|
||||
`yield`を持つ依存関係で`except`を使って例外をキャッチし、それを再度raiseしない(または新しい例外をraiseしない)場合、通常のPythonと同じように、FastAPIは例外があったことに気づけません:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008c_an_py39.py hl[15:16] *}
|
||||
|
||||
この場合、(`HTTPException`やそれに類するものをraiseしていないため)クライアントには適切に*HTTP 500 Internal Server Error*レスポンスが返りますが、サーバーには**ログが一切残らず**、何がエラーだったのかを示す他の手がかりもありません。 😱
|
||||
|
||||
### `yield`と`except`を持つ依存関係では常に`raise`する { #always-raise-in-dependencies-with-yield-and-except }
|
||||
|
||||
`yield`を持つ依存関係で例外をキャッチした場合、別の`HTTPException`などをraiseするのでない限り、**元の例外を再raiseすべきです**。
|
||||
|
||||
`raise`を使うと同じ例外を再raiseできます:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008d_an_py39.py hl[17] *}
|
||||
|
||||
これでクライアントは同じ*HTTP 500 Internal Server Error*レスポンスを受け取りますが、サーバーのログにはカスタムの`InternalError`が残ります。 😎
|
||||
|
||||
## `yield`を持つ依存関係の実行 { #execution-of-dependencies-with-yield }
|
||||
|
||||
実行の順序は多かれ少なかれ以下の図のようになります。時間は上から下へと流れていきます。そして、各列はコードを相互作用させたり、実行したりしている部分の一つです。
|
||||
|
||||
```mermaid
|
||||
@@ -142,32 +144,29 @@ participant dep as Dep with yield
|
||||
participant operation as Path Operation
|
||||
participant tasks as Background tasks
|
||||
|
||||
Note over client,tasks: Can raise exception for dependency, handled after response is sent
|
||||
Note over client,operation: Can raise HTTPException and can change the response
|
||||
Note over client,operation: Can raise exceptions, including HTTPException
|
||||
client ->> dep: Start request
|
||||
Note over dep: Run code up to yield
|
||||
opt raise
|
||||
dep -->> handler: Raise HTTPException
|
||||
opt raise Exception
|
||||
dep -->> handler: Raise Exception
|
||||
handler -->> client: HTTP error response
|
||||
dep -->> dep: Raise other exception
|
||||
end
|
||||
dep ->> operation: Run dependency, e.g. DB session
|
||||
opt raise
|
||||
operation -->> handler: Raise HTTPException
|
||||
operation -->> dep: Raise Exception (e.g. HTTPException)
|
||||
opt handle
|
||||
dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception
|
||||
end
|
||||
handler -->> client: HTTP error response
|
||||
operation -->> dep: Raise other exception
|
||||
end
|
||||
|
||||
operation ->> client: Return response to client
|
||||
Note over client,operation: Response is already sent, can't change it anymore
|
||||
opt Tasks
|
||||
operation -->> tasks: Send background tasks
|
||||
end
|
||||
opt Raise other exception
|
||||
tasks -->> dep: Raise other exception
|
||||
end
|
||||
Note over dep: After yield
|
||||
opt Handle other exception
|
||||
dep -->> dep: Handle exception, can't change response. E.g. close DB session.
|
||||
tasks -->> tasks: Handle exceptions in the background task code
|
||||
end
|
||||
```
|
||||
|
||||
@@ -181,15 +180,63 @@ participant tasks as Background tasks
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
この図は`HTTPException`を示していますが、[カスタム例外ハンドラ](../handling-errors.md#_4){.internal-link target=_blank}を作成することで、他の例外を発生させることもできます。そして、その例外は依存関係の終了コードではなく、そのカスタム例外ハンドラによって処理されます。
|
||||
|
||||
しかし例外ハンドラで処理されない例外を発生させた場合は、依存関係の終了コードで処理されます。
|
||||
*path operation 関数*のコードで例外をraiseした場合、`HTTPException`を含め、それはyieldを持つ依存関係に渡されます。ほとんどの場合、その例外が正しく処理されるように、`yield`を持つ依存関係から同じ例外、または新しい例外を再raiseしたくなるでしょう。
|
||||
|
||||
///
|
||||
|
||||
## コンテキストマネージャ
|
||||
## 早期終了と`scope` { #early-exit-and-scope }
|
||||
|
||||
### 「コンテキストマネージャ」とは
|
||||
通常、`yield`を持つ依存関係の終了コードは、クライアントに**レスポンスが送信された後**に実行されます。
|
||||
|
||||
しかし、*path operation 関数*からreturnした後に依存関係を使う必要がないと分かっている場合は、`Depends(scope="function")`を使って、**レスポンスが送信される前**に、*path operation 関数*のreturn後に依存関係を閉じるべきだとFastAPIに伝えられます。
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial008e_an_py39.py hl[12,16] *}
|
||||
|
||||
`Depends()`は、以下のいずれかを取る`scope`パラメータを受け取ります:
|
||||
|
||||
* `"function"`: リクエストを処理する*path operation 関数*の前に依存関係を開始し、*path operation 関数*の終了後に依存関係を終了しますが、クライアントにレスポンスが返される**前**に終了します。つまり、依存関係関数は*path operation 関数*の**周囲**で実行されます。
|
||||
* `"request"`: リクエストを処理する*path operation 関数*の前に依存関係を開始し(`"function"`を使用する場合と同様)、クライアントにレスポンスが返された**後**に終了します。つまり、依存関係関数は**リクエスト**とレスポンスのサイクルの**周囲**で実行されます。
|
||||
|
||||
指定されておらず、依存関係に`yield`がある場合、デフォルトで`scope`は`"request"`になります。
|
||||
|
||||
### サブ依存関係の`scope` { #scope-for-sub-dependencies }
|
||||
|
||||
`scope="request"`(デフォルト)を持つ依存関係を宣言する場合、どのサブ依存関係も`"request"`の`scope`を持つ必要があります。
|
||||
|
||||
しかし、`"function"`の`scope`を持つ依存関係は、`"function"`と`"request"`の`scope`を持つ依存関係を持てます。
|
||||
|
||||
これは、いずれの依存関係も、サブ依存関係より前に終了コードを実行できる必要があるためです(終了コードの実行中にサブ依存関係をまだ使う必要がある可能性があるためです)。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
|
||||
participant client as Client
|
||||
participant dep_req as Dep scope="request"
|
||||
participant dep_func as Dep scope="function"
|
||||
participant operation as Path Operation
|
||||
|
||||
client ->> dep_req: Start request
|
||||
Note over dep_req: Run code up to yield
|
||||
dep_req ->> dep_func: Pass dependency
|
||||
Note over dep_func: Run code up to yield
|
||||
dep_func ->> operation: Run path operation with dependency
|
||||
operation ->> dep_func: Return from path operation
|
||||
Note over dep_func: Run code after yield
|
||||
Note over dep_func: ✅ Dependency closed
|
||||
dep_func ->> client: Send response to client
|
||||
Note over client: Response sent
|
||||
Note over dep_req: Run code after yield
|
||||
Note over dep_req: ✅ Dependency closed
|
||||
```
|
||||
|
||||
## `yield`、`HTTPException`、`except`、バックグラウンドタスクを持つ依存関係 { #dependencies-with-yield-httpexception-except-and-background-tasks }
|
||||
|
||||
`yield`を持つ依存関係は、さまざまなユースケースをカバーし、いくつかの問題を修正するために、時間とともに進化してきました。
|
||||
|
||||
FastAPIの異なるバージョンで何が変わったのかを知りたい場合は、上級ガイドの[上級の依存関係 - `yield`、`HTTPException`、`except`、バックグラウンドタスクを持つ依存関係](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}で詳しく読めます。
|
||||
## コンテキストマネージャ { #context-managers }
|
||||
|
||||
### 「コンテキストマネージャ」とは { #what-are-context-managers }
|
||||
|
||||
「コンテキストマネージャ」とは、`with`文の中で使用できるPythonオブジェクトのことです。
|
||||
|
||||
@@ -205,9 +252,9 @@ with open("./somefile.txt") as f:
|
||||
|
||||
`with`ブロックが終了すると、例外があったとしてもファイルを確かに閉じます。
|
||||
|
||||
`yield`を依存関係を作成すると、**FastAPI** は内部的にそれをコンテキストマネージャに変換し、他の関連ツールと組み合わせます。
|
||||
`yield`を持つ依存関係を作成すると、**FastAPI** は内部的にそれをコンテキストマネージャに変換し、他の関連ツールと組み合わせます。
|
||||
|
||||
### `yield`を持つ依存関係でのコンテキストマネージャの使用
|
||||
### `yield`を持つ依存関係でのコンテキストマネージャの使用 { #using-context-managers-in-dependencies-with-yield }
|
||||
|
||||
/// warning | 注意
|
||||
|
||||
@@ -221,7 +268,7 @@ Pythonでは、<a href="https://docs.python.org/3/reference/datamodel.html#conte
|
||||
|
||||
また、依存関数の中で`with`や`async with`文を使用することによって`yield`を持つ **FastAPI** の依存関係の中でそれらを使用することができます:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial010.py hl[1,2,3,4,5,6,7,8,9,13] *}
|
||||
{* ../../docs_src/dependencies/tutorial010_py39.py hl[1:9,13] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# 依存関係 - 最初のステップ
|
||||
# 依存関係 { #dependencies }
|
||||
|
||||
** FastAPI** は非常に強力でありながら直感的な **<abbr title="コンポーネント、リソース、プロバイダ、サービス、インジェクタブルとしても知られている">依存性注入</abbr>** システムを持っています。
|
||||
**FastAPI** は非常に強力でありながら直感的な **<abbr title="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** システムを持っています。
|
||||
|
||||
それは非常にシンプルに使用できるように設計されており、開発者が他のコンポーネント **FastAPI** と統合するのが非常に簡単になるように設計されています。
|
||||
|
||||
## 「依存性注入」とは
|
||||
## 「Dependency Injection」とは { #what-is-dependency-injection }
|
||||
|
||||
**「依存性注入」** とは、プログラミングにおいて、コード(この場合は、*path operation関数*)が動作したり使用したりするために必要なもの(「依存関係」)を宣言する方法があることを意味します:
|
||||
**「Dependency Injection」** とは、プログラミングにおいて、コード(この場合は、*path operation 関数*)が動作したり使用したりするために必要なもの(「依存関係」)を宣言する方法があることを意味します:
|
||||
|
||||
そして、そのシステム(この場合は、**FastAPI**)は、必要な依存関係をコードに提供するために必要なことは何でも行います(依存関係を「注入」します)。
|
||||
|
||||
@@ -19,27 +19,27 @@
|
||||
|
||||
これらすべてを、コードの繰り返しを最小限に抑えながら行います。
|
||||
|
||||
## 最初のステップ
|
||||
## 最初のステップ { #first-steps }
|
||||
|
||||
非常にシンプルな例を見てみましょう。あまりにもシンプルなので、今のところはあまり参考にならないでしょう。
|
||||
|
||||
しかし、この方法では **依存性注入** システムがどのように機能するかに焦点を当てることができます。
|
||||
しかし、この方法では **Dependency Injection** システムがどのように機能するかに焦点を当てることができます。
|
||||
|
||||
### 依存関係の作成
|
||||
### 依存関係(「dependable」)の作成 { #create-a-dependency-or-dependable }
|
||||
|
||||
まずは依存関係に注目してみましょう。
|
||||
|
||||
以下のように、*path operation関数*と同じパラメータを全て取ることができる関数にすぎません:
|
||||
以下のように、*path operation 関数*と同じパラメータを全て取ることができる関数にすぎません:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial001.py hl[8,9] *}
|
||||
{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[8:9] *}
|
||||
|
||||
これだけです。
|
||||
|
||||
**2行**。
|
||||
|
||||
そして、それはすべての*path operation関数*が持っているのと同じ形と構造を持っています。
|
||||
そして、それはすべての*path operation 関数*が持っているのと同じ形と構造を持っています。
|
||||
|
||||
「デコレータ」を含まない(`@app.get("/some-path")`を含まない)*path operation関数*と考えることもできます。
|
||||
「デコレータ」を含まない(`@app.get("/some-path")`を含まない)*path operation 関数*と考えることもできます。
|
||||
|
||||
そして何でも返すことができます。
|
||||
|
||||
@@ -51,15 +51,25 @@
|
||||
|
||||
そして、これらの値を含む`dict`を返します。
|
||||
|
||||
### `Depends`のインポート
|
||||
/// info | 情報
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial001.py hl[3] *}
|
||||
FastAPI はバージョン 0.95.0 で `Annotated` のサポートを追加し(そして推奨し始めました)。
|
||||
|
||||
### "dependant"での依存関係の宣言
|
||||
古いバージョンを使用している場合、`Annotated` を使おうとするとエラーになります。
|
||||
|
||||
*path operation関数*のパラメータに`Body`や`Query`などを使用するのと同じように、新しいパラメータに`Depends`を使用することができます:
|
||||
`Annotated` を使用する前に、少なくとも 0.95.1 まで [FastAPI のバージョンをアップグレード](../../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank} してください。
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial001.py hl[13,18] *}
|
||||
///
|
||||
|
||||
### `Depends`のインポート { #import-depends }
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[3] *}
|
||||
|
||||
### 「dependant」での依存関係の宣言 { #declare-the-dependency-in-the-dependant }
|
||||
|
||||
*path operation 関数*のパラメータに`Body`や`Query`などを使用するのと同じように、新しいパラメータに`Depends`を使用することができます:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial001_an_py310.py hl[13,18] *}
|
||||
|
||||
関数のパラメータに`Depends`を使用するのは`Body`や`Query`などと同じですが、`Depends`の動作は少し異なります。
|
||||
|
||||
@@ -67,7 +77,9 @@
|
||||
|
||||
このパラメータは関数のようなものである必要があります。
|
||||
|
||||
そして、その関数は、*path operation関数*が行うのと同じ方法でパラメータを取ります。
|
||||
直接**呼び出しません**(末尾に括弧を付けません)。`Depends()` のパラメータとして渡すだけです。
|
||||
|
||||
そして、その関数は、*path operation 関数*が行うのと同じ方法でパラメータを取ります。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
@@ -79,7 +91,7 @@
|
||||
|
||||
* 依存関係("dependable")関数を正しいパラメータで呼び出します。
|
||||
* 関数の結果を取得します。
|
||||
* *path operation関数*のパラメータにその結果を代入してください。
|
||||
* *path operation 関数*のパラメータにその結果を代入してください。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
@@ -92,7 +104,7 @@ common_parameters --> read_items
|
||||
common_parameters --> read_users
|
||||
```
|
||||
|
||||
この方法では、共有されるコードを一度書き、**FastAPI** が*path operations*のための呼び出しを行います。
|
||||
この方法では、共有されるコードを一度書き、**FastAPI** が*path operation*のための呼び出しを行います。
|
||||
|
||||
/// check | 確認
|
||||
|
||||
@@ -102,59 +114,85 @@ common_parameters --> read_users
|
||||
|
||||
///
|
||||
|
||||
## `async`にするかどうか
|
||||
## `Annotated` 依存関係の共有 { #share-annotated-dependencies }
|
||||
|
||||
依存関係は **FastAPI**(*path operation関数*と同じ)からも呼び出されるため、関数を定義する際にも同じルールが適用されます。
|
||||
上の例では、ほんの少し **コードの重複** があることがわかります。
|
||||
|
||||
`common_parameters()` 依存関係を使う必要があるときは、型アノテーションと `Depends()` を含むパラメータ全体を書く必要があります:
|
||||
|
||||
```Python
|
||||
commons: Annotated[dict, Depends(common_parameters)]
|
||||
```
|
||||
|
||||
しかし、`Annotated` を使用しているので、その `Annotated` 値を変数に格納して複数箇所で使えます:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial001_02_an_py310.py hl[12,16,21] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
これはただの標準 Python で、「type alias」と呼ばれ、**FastAPI** 固有のものではありません。
|
||||
|
||||
しかし **FastAPI** は `Annotated` を含む Python 標準に基づいているため、このテクニックをコードで使えます。 😎
|
||||
|
||||
///
|
||||
|
||||
依存関係は期待どおりに動作し続け、**一番良い点** は **型情報が保持される** ことです。つまり、エディタは **自動補完**、**インラインエラー** などを提供し続けられます。`mypy` のような他のツールでも同様です。
|
||||
|
||||
これは **大規模なコードベース** で、**同じ依存関係** を **多くの *path operation*** で何度も使う場合に特に役立ちます。
|
||||
|
||||
## `async`にするかどうか { #to-async-or-not-to-async }
|
||||
|
||||
依存関係は **FastAPI**(*path operation 関数*と同じ)からも呼び出されるため、関数を定義する際にも同じルールが適用されます。
|
||||
|
||||
`async def`や通常の`def`を使用することができます。
|
||||
|
||||
また、通常の`def`*path operation関数*の中に`async def`を入れて依存関係を宣言したり、`async def`*path operation関数*の中に`def`を入れて依存関係を宣言したりすることなどができます。
|
||||
また、通常の`def`*path operation 関数*の中に`async def`を入れて依存関係を宣言したり、`async def`*path operation 関数*の中に`def`を入れて依存関係を宣言したりすることなどができます。
|
||||
|
||||
それは重要ではありません。**FastAPI** は何をすべきかを知っています。
|
||||
|
||||
/// note | 備考
|
||||
|
||||
わからない場合は、ドキュメントの[Async: *"In a hurry?"*](../../async.md){.internal-link target=_blank}の中の`async`と`await`についてのセクションを確認してください。
|
||||
わからない場合は、ドキュメントの[Async: *"In a hurry?"*](../../async.md#in-a-hurry){.internal-link target=_blank}の中の`async`と`await`についてのセクションを確認してください。
|
||||
|
||||
///
|
||||
|
||||
## OpenAPIとの統合
|
||||
## OpenAPIとの統合 { #integrated-with-openapi }
|
||||
|
||||
依存関係(およびサブ依存関係)のすべてのリクエスト宣言、検証、および要件は、同じOpenAPIスキーマに統合されます。
|
||||
|
||||
つまり、対話型ドキュメントにはこれらの依存関係から得られる全ての情報も含まれているということです:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/dependencies/image01.png">
|
||||
<img src="/img/tutorial/dependencies/image01.png">
|
||||
|
||||
## 簡単な使い方
|
||||
## 簡単な使い方 { #simple-usage }
|
||||
|
||||
見てみると、*path*と*operation*が一致した時に*path operation関数*が宣言されていて、**FastAPI** が正しいパラメータで関数を呼び出してリクエストからデータを抽出する処理をしています。
|
||||
見てみると、*path*と*operation*が一致した時に*path operation 関数*が宣言されていて、**FastAPI** が正しいパラメータで関数を呼び出してリクエストからデータを抽出する処理をしています。
|
||||
|
||||
実は、すべての(あるいはほとんどの)Webフレームワークは、このように動作します。
|
||||
|
||||
これらの関数を直接呼び出すことはありません。これらの関数はフレームワーク(この場合は、**FastAPI**)によって呼び出されます。
|
||||
|
||||
依存性注入システムでは、**FastAPI** に*path operation*もまた、*path operation関数*の前に実行されるべき他の何かに「依存」していることを伝えることができ、**FastAPI** がそれを実行し、結果を「注入」することを引き受けます。
|
||||
Dependency Injection システムでは、**FastAPI** に*path operation 関数*もまた、*path operation 関数*の前に実行されるべき他の何かに「依存」していることを伝えることができ、**FastAPI** がそれを実行し、結果を「注入」することを引き受けます。
|
||||
|
||||
他にも、「依存性注入」と同じような考えの一般的な用語があります:
|
||||
他にも、「dependency injection」と同じような考えの一般的な用語があります:
|
||||
|
||||
* リソース
|
||||
* プロバイダ
|
||||
* サービス
|
||||
* インジェクタブル
|
||||
* コンポーネント
|
||||
* resources
|
||||
* providers
|
||||
* services
|
||||
* injectables
|
||||
* components
|
||||
|
||||
## **FastAPI** プラグイン
|
||||
## **FastAPI** プラグイン { #fastapi-plug-ins }
|
||||
|
||||
統合や「プラグイン」は **依存性注入** システムを使って構築することができます。しかし、実際には、**「プラグイン」を作成する必要はありません**。依存関係を使用することで、無限の数の統合やインタラクションを宣言することができ、それが**path operation関数*で利用可能になるからです。
|
||||
統合や「プラグイン」は **Dependency Injection** システムを使って構築することができます。しかし、実際には、**「プラグイン」を作成する必要はありません**。依存関係を使用することで、無限の数の統合やインタラクションを宣言することができ、それが*path operation 関数*で利用可能になるからです。
|
||||
|
||||
依存関係は非常にシンプルで直感的な方法で作成することができ、必要なPythonパッケージをインポートするだけで、*文字通り*数行のコードでAPI関数と統合することができます。
|
||||
|
||||
次の章では、リレーショナルデータベースやNoSQLデータベース、セキュリティなどについて、その例を見ていきます。
|
||||
|
||||
## **FastAPI** 互換性
|
||||
## **FastAPI** 互換性 { #fastapi-compatibility }
|
||||
|
||||
依存性注入システムがシンプルなので、**FastAPI** は以下のようなものと互換性があります:
|
||||
dependency injection システムがシンプルなので、**FastAPI** は以下のようなものと互換性があります:
|
||||
|
||||
* すべてのリレーショナルデータベース
|
||||
* NoSQLデータベース
|
||||
@@ -165,15 +203,15 @@ common_parameters --> read_users
|
||||
* レスポンスデータ注入システム
|
||||
* など。
|
||||
|
||||
## シンプルでパワフル
|
||||
## シンプルでパワフル { #simple-and-powerful }
|
||||
|
||||
階層依存性注入システムは、定義や使用方法が非常にシンプルであるにもかかわらず、非常に強力なものとなっています。
|
||||
階層的な dependency injection システムは、定義や使用方法が非常にシンプルであるにもかかわらず、非常に強力なものとなっています。
|
||||
|
||||
依存関係事態を定義する依存関係を定義することができます。
|
||||
依存関係が、さらに依存関係を定義することもできます。
|
||||
|
||||
最終的には、依存関係の階層ツリーが構築され、**依存性注入**システムが、これらの依存関係(およびそのサブ依存関係)をすべて解決し、各ステップで結果を提供(注入)します。
|
||||
最終的には、依存関係の階層ツリーが構築され、**Dependency Injection**システムが、これらの依存関係(およびそのサブ依存関係)をすべて解決し、各ステップで結果を提供(注入)します。
|
||||
|
||||
例えば、4つのAPIエンドポイント(*path operations*)があるとします:
|
||||
例えば、4つのAPIエンドポイント(*path operation*)があるとします:
|
||||
|
||||
* `/items/public/`
|
||||
* `/items/private/`
|
||||
@@ -205,8 +243,8 @@ admin_user --> activate_user
|
||||
paying_user --> pro_items
|
||||
```
|
||||
|
||||
## **OpenAPI** との統合
|
||||
## **OpenAPI** との統合 { #integrated-with-openapi_1 }
|
||||
|
||||
これら全ての依存関係は、要件を宣言すると同時に、*path operations*にパラメータやバリデーションを追加します。
|
||||
これら全ての依存関係は、要件を宣言すると同時に、*path operation*にパラメータやバリデーションを追加します。
|
||||
|
||||
**FastAPI** はそれをすべてOpenAPIスキーマに追加して、対話型のドキュメントシステムに表示されるようにします。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# サブ依存関係
|
||||
# サブ依存関係 { #sub-dependencies }
|
||||
|
||||
**サブ依存関係** を持つ依存関係を作成することができます。
|
||||
|
||||
@@ -6,21 +6,21 @@
|
||||
|
||||
**FastAPI** はそれらを解決してくれます。
|
||||
|
||||
### 最初の依存関係「依存可能なもの」
|
||||
## 最初の依存関係「依存可能なもの」 { #first-dependency-dependable }
|
||||
|
||||
以下のような最初の依存関係(「依存可能なもの」)を作成することができます:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial005.py hl[8,9] *}
|
||||
{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[8:9] *}
|
||||
|
||||
これはオプショナルのクエリパラメータ`q`を`str`として宣言し、それを返すだけです。
|
||||
|
||||
これは非常にシンプルです(あまり便利ではありません)が、サブ依存関係がどのように機能するかに焦点を当てるのに役立ちます。
|
||||
|
||||
### 第二の依存関係 「依存可能なもの」と「依存」
|
||||
## 第二の依存関係 「依存可能なもの」と「依存」 { #second-dependency-dependable-and-dependant }
|
||||
|
||||
そして、別の依存関数(「依存可能なもの」)を作成して、同時にそれ自身の依存関係を宣言することができます(つまりそれ自身も「依存」です):
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial005.py hl[13] *}
|
||||
{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[13] *}
|
||||
|
||||
宣言されたパラメータに注目してみましょう:
|
||||
|
||||
@@ -29,15 +29,15 @@
|
||||
* また、オプショナルの`last_query`クッキーを`str`として宣言します。
|
||||
* ユーザーがクエリ`q`を提供しなかった場合、クッキーに保存していた最後に使用したクエリを使用します。
|
||||
|
||||
### 依存関係の使用
|
||||
## 依存関係の使用 { #use-the-dependency }
|
||||
|
||||
以下のように依存関係を使用することができます:
|
||||
|
||||
{* ../../docs_src/dependencies/tutorial005.py hl[21] *}
|
||||
{* ../../docs_src/dependencies/tutorial005_an_py310.py hl[23] *}
|
||||
|
||||
/// info | 情報
|
||||
|
||||
*path operation関数*の中で宣言している依存関係は`query_or_cookie_extractor`の1つだけであることに注意してください。
|
||||
*path operation 関数*の中で宣言している依存関係は`query_or_cookie_extractor`の1つだけであることに注意してください。
|
||||
|
||||
しかし、**FastAPI** は`query_extractor`を最初に解決し、その結果を`query_or_cookie_extractor`を呼び出す時に渡す必要があることを知っています。
|
||||
|
||||
@@ -54,24 +54,43 @@ read_query["/items/"]
|
||||
query_extractor --> query_or_cookie_extractor --> read_query
|
||||
```
|
||||
|
||||
## 同じ依存関係の複数回の使用
|
||||
## 同じ依存関係の複数回の使用 { #using-the-same-dependency-multiple-times }
|
||||
|
||||
依存関係の1つが同じ*path operation*に対して複数回宣言されている場合、例えば、複数の依存関係が共通のサブ依存関係を持っている場合、**FastAPI** はリクエストごとに1回だけそのサブ依存関係を呼び出します。
|
||||
依存関係の1つが同じ*path operation*に対して複数回宣言されている場合、例えば、複数の依存関係が共通のサブ依存関係を持っている場合、**FastAPI** はリクエストごとに1回だけそのサブ依存関係を呼び出します。
|
||||
|
||||
そして、返された値を<abbr title="計算された値・生成された値を保存するユーティリティまたはシステム、再計算する代わりに再利用するためのもの">「キャッシュ」</abbr>に保存し、同じリクエストに対して依存関係を何度も呼び出す代わりに、特定のリクエストでそれを必要とする全ての「依存関係」に渡すことになります。
|
||||
そして、返された値を<abbr title="A utility/system to store computed/generated values, to reuse them instead of computing them again. – 計算/生成された値を保存し、再計算する代わりに再利用するためのユーティリティ/システム。">「キャッシュ」</abbr>に保存し、同じリクエストに対して依存関係を何度も呼び出す代わりに、その特定のリクエストでそれを必要とする全ての「依存」に渡すことになります。
|
||||
|
||||
高度なシナリオでは、「キャッシュされた」値を使うのではなく、同じリクエストの各ステップ(おそらく複数回)で依存関係を呼び出す必要があることがわかっている場合、`Depens`を使用する際に、`use_cache=False`というパラメータを設定することができます。
|
||||
高度なシナリオでは、「キャッシュされた」値を使うのではなく、同じリクエストの各ステップ(おそらく複数回)で依存関係を呼び出す必要があることがわかっている場合、`Depends`を使用する際に、`use_cache=False`というパラメータを設定することができます:
|
||||
|
||||
//// tab | Python 3.9+
|
||||
|
||||
```Python hl_lines="1"
|
||||
async def needy_dependency(fresh_value: Annotated[str, Depends(get_value, use_cache=False)]):
|
||||
return {"fresh_value": fresh_value}
|
||||
```
|
||||
|
||||
////
|
||||
|
||||
//// tab | Python 3.9+ 非Annotated
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
可能であれば`Annotated`版を使うことを推奨します。
|
||||
|
||||
///
|
||||
|
||||
```Python hl_lines="1"
|
||||
async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):
|
||||
return {"fresh_value": fresh_value}
|
||||
```
|
||||
|
||||
## まとめ
|
||||
////
|
||||
|
||||
ここで使われている派手な言葉は別にして、**依存性注入** システムは非常にシンプルです。
|
||||
## まとめ { #recap }
|
||||
|
||||
*path operation関数*と同じように見えるただの関数です。
|
||||
ここで使われている派手な言葉は別にして、**Dependency Injection** システムは非常にシンプルです。
|
||||
|
||||
*path operation 関数*と同じように見えるただの関数です。
|
||||
|
||||
しかし、それでも非常に強力で、任意の深くネストされた依存関係「グラフ」(ツリー)を宣言することができます。
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# JSON互換エンコーダ
|
||||
# JSON互換エンコーダ { #json-compatible-encoder }
|
||||
|
||||
データ型(Pydanticモデルのような)をJSONと互換性のあるもの(`dict`や`list`など)に変更する必要がある場合があります。
|
||||
データ型(Pydanticモデルのような)をJSONと互換性のあるもの(`dict`や`list`など)に変換する必要があるケースがあります。
|
||||
|
||||
例えば、データベースに保存する必要がある場合です。
|
||||
|
||||
そのために、**FastAPI** は`jsonable_encoder()`関数を提供しています。
|
||||
|
||||
## `jsonable_encoder`の使用
|
||||
## `jsonable_encoder`の使用 { #using-the-jsonable-encoder }
|
||||
|
||||
JSON互換のデータのみを受信するデータベース`fake_db`があるとしましょう。
|
||||
|
||||
例えば、`datetime`オブジェクトはJSONと互換性がないので、このデーターベースには受け取られません。
|
||||
例えば、`datetime`オブジェクトはJSONと互換性がないので、受け取られません。
|
||||
|
||||
そのため、`datetime`オブジェクトは<a href="https://en.wikipedia.org/wiki/ISO_8601" class="external-link" target="_blank">ISO形式</a>のデータを含む`str`に変換されなければなりません。
|
||||
|
||||
@@ -20,7 +20,7 @@ JSON互換のデータのみを受信するデータベース`fake_db`がある
|
||||
|
||||
Pydanticモデルのようなオブジェクトを受け取り、JSON互換版を返します:
|
||||
|
||||
{* ../../docs_src/encoder/tutorial001.py hl[5,22] *}
|
||||
{* ../../docs_src/encoder/tutorial001_py310.py hl[4,21] *}
|
||||
|
||||
この例では、Pydanticモデルを`dict`に、`datetime`を`str`に変換します。
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 追加データ型
|
||||
# 追加データ型 { #extra-data-types }
|
||||
|
||||
今までは、以下のような一般的なデータ型を使用してきました:
|
||||
今まで、以下のような一般的なデータ型を使用してきました:
|
||||
|
||||
* `int`
|
||||
* `float`
|
||||
@@ -11,13 +11,13 @@
|
||||
|
||||
そして、今まで見てきたのと同じ機能を持つことになります:
|
||||
|
||||
* 素晴らしいエディタのサポート
|
||||
* 受信したリクエストからのデータ変換
|
||||
* レスポンスデータのデータ変換
|
||||
* データの検証
|
||||
* 自動注釈と文書化
|
||||
* 素晴らしいエディタのサポート。
|
||||
* 受信したリクエストからのデータ変換。
|
||||
* レスポンスデータのデータ変換。
|
||||
* データの検証。
|
||||
* 自動注釈と文書化。
|
||||
|
||||
## 他のデータ型
|
||||
## 他のデータ型 { #other-data-types }
|
||||
|
||||
ここでは、使用できる追加のデータ型のいくつかを紹介します:
|
||||
|
||||
@@ -26,17 +26,17 @@
|
||||
* リクエストとレスポンスでは`str`として表現されます。
|
||||
* `datetime.datetime`:
|
||||
* Pythonの`datetime.datetime`です。
|
||||
* リクエストとレスポンスはISO 8601形式の`str`で表現されます: `2008-09-15T15:53:00+05:00`
|
||||
* リクエストとレスポンスはISO 8601形式の`str`で表現されます(例: `2008-09-15T15:53:00+05:00`)。
|
||||
* `datetime.date`:
|
||||
* Pythonの`datetime.date`です。
|
||||
* リクエストとレスポンスはISO 8601形式の`str`で表現されます: `2008-09-15`
|
||||
* Python `datetime.date`。
|
||||
* リクエストとレスポンスはISO 8601形式の`str`で表現されます(例: `2008-09-15`)。
|
||||
* `datetime.time`:
|
||||
* Pythonの`datetime.time`.
|
||||
* リクエストとレスポンスはISO 8601形式の`str`で表現されます: `14:23:55.003`
|
||||
* Pythonの`datetime.time`。
|
||||
* リクエストとレスポンスはISO 8601形式の`str`で表現されます(例: `14:23:55.003`)。
|
||||
* `datetime.timedelta`:
|
||||
* Pythonの`datetime.timedelta`です。
|
||||
* リクエストとレスポンスでは合計秒数の`float`で表現されます。
|
||||
* Pydanticでは「ISO 8601 time diff encoding」として表現することも可能です。<a href="https://docs.pydantic.dev/latest/concepts/serialization/" class="external-link" target="_blank">詳細はドキュメントを参照してください</a>。
|
||||
* Pydanticでは「ISO 8601 time diff encoding」として表現することも可能です。<a href="https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers" class="external-link" target="_blank">詳細はドキュメントを参照してください</a>。
|
||||
* `frozenset`:
|
||||
* リクエストとレスポンスでは`set`と同じように扱われます:
|
||||
* リクエストでは、リストが読み込まれ、重複を排除して`set`に変換されます。
|
||||
@@ -45,18 +45,18 @@
|
||||
* `bytes`:
|
||||
* Pythonの標準的な`bytes`です。
|
||||
* リクエストとレスポンスでは`str`として扱われます。
|
||||
* 生成されたスキーマは`str`で`binary`の「フォーマット」持つことを指定します。
|
||||
* 生成されたスキーマは`str`で`binary`の「フォーマット」を持つことを指定します。
|
||||
* `Decimal`:
|
||||
* Pythonの標準的な`Decimal`です。
|
||||
* リクエストやレスポンスでは`float`と同じように扱います。
|
||||
* リクエストとレスポンスでは`float`と同じように扱われます。
|
||||
* Pydanticの全ての有効な型はこちらで確認できます: <a href="https://docs.pydantic.dev/latest/usage/types/types/" class="external-link" target="_blank">Pydantic data types</a>。
|
||||
|
||||
* Pydanticの全ての有効な型はこちらで確認できます: <a href="https://docs.pydantic.dev/latest/concepts/types/" class="external-link" target="_blank">Pydantic data types</a>。
|
||||
## 例
|
||||
## 例 { #example }
|
||||
|
||||
ここでは、上記の型のいくつかを使用したパラメータを持つ*path operation*の例を示します。
|
||||
|
||||
{* ../../docs_src/extra_data_types/tutorial001.py hl[1,2,12:16] *}
|
||||
{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[1,3,12:16] *}
|
||||
|
||||
関数内のパラメータは自然なデータ型を持っていることに注意してください。そして、以下のように通常の日付操作を行うことができます:
|
||||
関数内のパラメータは自然なデータ型を持っていることに注意してください。そして、例えば、以下のように通常の日付操作を行うことができます:
|
||||
|
||||
{* ../../docs_src/extra_data_types/tutorial001.py hl[18,19] *}
|
||||
{* ../../docs_src/extra_data_types/tutorial001_an_py310.py hl[18:19] *}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# モデル - より詳しく
|
||||
# Extra Models { #extra-models }
|
||||
|
||||
先ほどの例に続き、複数の関連モデルを持つことが一般的です。
|
||||
先ほどの例に続き、複数の関連モデルを持つことは一般的です。
|
||||
|
||||
これはユーザーモデルの場合は特にそうです。なぜなら:
|
||||
|
||||
@@ -8,27 +8,27 @@
|
||||
* **出力モデル**はパスワードをもつべきではありません。
|
||||
* **データベースモデル**はおそらくハッシュ化されたパスワードが必要になるでしょう。
|
||||
|
||||
/// danger | 危険
|
||||
/// danger
|
||||
|
||||
ユーザーの平文のパスワードは絶対に保存しないでください。常に認証に利用可能な「安全なハッシュ」を保存してください。
|
||||
ユーザーの平文のパスワードは絶対に保存しないでください。常に検証できる「安全なハッシュ」を保存してください。
|
||||
|
||||
知らない方は、[セキュリティの章](security/simple-oauth2.md#password-hashing){.internal-link target=_blank}で「パスワードハッシュ」とは何かを学ぶことができます。
|
||||
|
||||
///
|
||||
|
||||
## 複数のモデル
|
||||
## Multiple models { #multiple-models }
|
||||
|
||||
ここでは、パスワードフィールドをもつモデルがどのように見えるのか、また、どこで使われるのか、大まかなイメージを紹介します:
|
||||
|
||||
{* ../../docs_src/extra_models/tutorial001.py hl[9,11,16,22,24,29:30,33:35,40:41] *}
|
||||
{* ../../docs_src/extra_models/tutorial001_py310.py hl[7,9,14,20,22,27:28,31:33,38:39] *}
|
||||
|
||||
### `**user_in.dict()`について
|
||||
### About `**user_in.model_dump()` { #about-user-in-model-dump }
|
||||
|
||||
#### Pydanticの`.dict()`
|
||||
#### Pydanticの`.model_dump()` { #pydantics-model-dump }
|
||||
|
||||
`user_in`は`UserIn`クラスのPydanticモデルです。
|
||||
|
||||
Pydanticモデルには、モデルのデータを含む`dict`を返す`.dict()`メソッドがあります。
|
||||
Pydanticモデルには、モデルのデータを含む`dict`を返す`.model_dump()`メソッドがあります。
|
||||
|
||||
そこで、以下のようなPydanticオブジェクト`user_in`を作成すると:
|
||||
|
||||
@@ -39,7 +39,7 @@ user_in = UserIn(username="john", password="secret", email="john.doe@example.com
|
||||
そして呼び出すと:
|
||||
|
||||
```Python
|
||||
user_dict = user_in.dict()
|
||||
user_dict = user_in.model_dump()
|
||||
```
|
||||
|
||||
これで変数`user_dict`のデータを持つ`dict`ができました。(これはPydanticモデルのオブジェクトの代わりに`dict`です)。
|
||||
@@ -61,7 +61,7 @@ print(user_dict)
|
||||
}
|
||||
```
|
||||
|
||||
#### `dict`の展開
|
||||
#### `dict`の展開 { #unpacking-a-dict }
|
||||
|
||||
`user_dict`のような`dict`を受け取り、それを`**user_dict`を持つ関数(またはクラス)に渡すと、Pythonはそれを「展開」します。これは`user_dict`のキーと値を直接キー・バリューの引数として渡します。
|
||||
|
||||
@@ -93,31 +93,31 @@ UserInDB(
|
||||
)
|
||||
```
|
||||
|
||||
#### 別のモデルからつくるPydanticモデル
|
||||
#### 別のモデルの内容からつくるPydanticモデル { #a-pydantic-model-from-the-contents-of-another }
|
||||
|
||||
上述の例では`user_in.dict()`から`user_dict`をこのコードのように取得していますが:
|
||||
上述の例では`user_in.model_dump()`から`user_dict`をこのコードのように取得していますが:
|
||||
|
||||
```Python
|
||||
user_dict = user_in.dict()
|
||||
user_dict = user_in.model_dump()
|
||||
UserInDB(**user_dict)
|
||||
```
|
||||
|
||||
これは以下と同等です:
|
||||
|
||||
```Python
|
||||
UserInDB(**user_in.dict())
|
||||
UserInDB(**user_in.model_dump())
|
||||
```
|
||||
|
||||
...なぜなら`user_in.dict()`は`dict`であり、`**`を付与して`UserInDB`を渡してPythonに「展開」させているからです。
|
||||
...なぜなら`user_in.model_dump()`は`dict`であり、`**`を付与して`UserInDB`を渡してPythonに「展開」させているからです。
|
||||
|
||||
そこで、別のPydanticモデルのデータからPydanticモデルを取得します。
|
||||
|
||||
#### `dict`の展開と追加引数
|
||||
#### `dict`の展開と追加キーワード { #unpacking-a-dict-and-extra-keywords }
|
||||
|
||||
そして、追加のキーワード引数`hashed_password=hashed_password`を以下のように追加すると:
|
||||
|
||||
```Python
|
||||
UserInDB(**user_in.dict(), hashed_password=hashed_password)
|
||||
UserInDB(**user_in.model_dump(), hashed_password=hashed_password)
|
||||
```
|
||||
|
||||
...以下のようになります:
|
||||
@@ -132,13 +132,13 @@ UserInDB(
|
||||
)
|
||||
```
|
||||
|
||||
/// warning | 注意
|
||||
/// warning
|
||||
|
||||
サポートしている追加機能は、データの可能な流れをデモするだけであり、もちろん本当のセキュリティを提供しているわけではありません。
|
||||
追加のサポート関数`fake_password_hasher`と`fake_save_user`は、データの可能な流れをデモするだけであり、もちろん本当のセキュリティを提供しているわけではありません。
|
||||
|
||||
///
|
||||
|
||||
## 重複の削減
|
||||
## Reduce duplication { #reduce-duplication }
|
||||
|
||||
コードの重複を減らすことは、**FastAPI**の中核的なアイデアの1つです。
|
||||
|
||||
@@ -152,40 +152,60 @@ UserInDB(
|
||||
|
||||
データの変換、検証、文書化などはすべて通常通りに動作します。
|
||||
|
||||
このようにして、モデル間の違いだけを宣言することができます:
|
||||
このようにして、モデル間の違いだけを宣言することができます(平文の`password`、`hashed_password`、パスワードなし):
|
||||
|
||||
{* ../../docs_src/extra_models/tutorial002.py hl[9,15,16,19,20,23,24] *}
|
||||
{* ../../docs_src/extra_models/tutorial002_py310.py hl[7,13:14,17:18,21:22] *}
|
||||
|
||||
## `Union`または`anyOf`
|
||||
## `Union` or `anyOf` { #union-or-anyof }
|
||||
|
||||
レスポンスを2つの型の`Union`として宣言することができます。
|
||||
レスポンスを2つ以上の型の`Union`として宣言できます。つまり、そのレスポンスはそれらのいずれかになります。
|
||||
|
||||
OpenAPIでは`anyOf`で定義されます。
|
||||
|
||||
そのためには、標準的なPythonの型ヒント<a href="https://docs.python.org/3/library/typing.html#typing.Union" class="external-link" target="_blank">`typing.Union`</a>を使用します:
|
||||
|
||||
{* ../../docs_src/extra_models/tutorial003.py hl[1,14,15,18,19,20,33] *}
|
||||
/// note | 備考
|
||||
|
||||
## モデルのリスト
|
||||
<a href="https://docs.pydantic.dev/latest/concepts/types/#unions" class="external-link" target="_blank">`Union`</a>を定義する場合は、最も具体的な型を先に、その後により具体性の低い型を含めてください。以下の例では、より具体的な`PlaneItem`が`Union[PlaneItem, CarItem]`内で`CarItem`より前に来ています。
|
||||
|
||||
同じように、オブジェクトのリストのレスポンスを宣言することができます。
|
||||
///
|
||||
|
||||
そのためには、標準のPythonの`typing.List`を使用する:
|
||||
{* ../../docs_src/extra_models/tutorial003_py310.py hl[1,14:15,18:20,33] *}
|
||||
|
||||
{* ../../docs_src/extra_models/tutorial004.py hl[1,20] *}
|
||||
### Python 3.10の`Union` { #union-in-python-3-10 }
|
||||
|
||||
## 任意の`dict`を持つレスポンス
|
||||
この例では、引数`response_model`の値として`Union[PlaneItem, CarItem]`を渡しています。
|
||||
|
||||
**型アノテーション**に書くのではなく、**引数の値**として渡しているため、Python 3.10でも`Union`を使う必要があります。
|
||||
|
||||
型アノテーションであれば、次のように縦棒を使用できました:
|
||||
|
||||
```Python
|
||||
some_variable: PlaneItem | CarItem
|
||||
```
|
||||
|
||||
しかし、これを代入で`response_model=PlaneItem | CarItem`のように書くと、Pythonはそれを型アノテーションとして解釈するのではなく、`PlaneItem`と`CarItem`の間で**無効な操作**を行おうとしてしまうため、エラーになります。
|
||||
|
||||
## List of models { #list-of-models }
|
||||
|
||||
同じように、オブジェクトのリストのレスポンスを宣言できます。
|
||||
|
||||
そのためには、標準のPythonの`typing.List`(またはPython 3.9以降では単に`list`)を使用します:
|
||||
|
||||
{* ../../docs_src/extra_models/tutorial004_py39.py hl[18] *}
|
||||
|
||||
## Response with arbitrary `dict` { #response-with-arbitrary-dict }
|
||||
|
||||
また、Pydanticモデルを使用せずに、キーと値の型だけを定義した任意の`dict`を使ってレスポンスを宣言することもできます。
|
||||
|
||||
これは、有効なフィールド・属性名(Pydanticモデルに必要なもの)を事前に知らない場合に便利です。
|
||||
|
||||
この場合、`typing.Dict`を使用することができます:
|
||||
この場合、`typing.Dict`(またはPython 3.9以降では単に`dict`)を使用できます:
|
||||
|
||||
{* ../../docs_src/extra_models/tutorial005.py hl[1,8] *}
|
||||
{* ../../docs_src/extra_models/tutorial005_py39.py hl[6] *}
|
||||
|
||||
## まとめ
|
||||
## Recap { #recap }
|
||||
|
||||
複数のPydanticモデルを使用し、ケースごとに自由に継承します。
|
||||
|
||||
エンティティが異なる「状態」を持たなければならない場合は、エンティティごとに単一のデータモデルを持つ必要はありません。`password` や `password_hash` やパスワードなしなどのいくつかの「状態」をもつユーザー「エンティティ」の場合の様にすれば良いです。
|
||||
エンティティが異なる「状態」を持たなければならない場合は、エンティティごとに単一のデータモデルを持つ必要はありません。`password`、`password_hash`、パスワードなしを含む状態を持つユーザー「エンティティ」の場合と同様です。
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 最初のステップ
|
||||
# 最初のステップ { #first-steps }
|
||||
|
||||
最もシンプルなFastAPIファイルは以下のようになります:
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001.py *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py *}
|
||||
|
||||
これを`main.py`にコピーします。
|
||||
|
||||
@@ -11,27 +11,43 @@
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
<span style="color: green;">INFO</span>: Started reloader process [28720]
|
||||
<span style="color: green;">INFO</span>: Started server process [28722]
|
||||
<span style="color: green;">INFO</span>: Waiting for application startup.
|
||||
<span style="color: green;">INFO</span>: Application startup complete.
|
||||
<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">'/home/user/code/awesomeapp'</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>
|
||||
|
||||
/// note | 備考
|
||||
|
||||
`uvicorn main:app`は以下を示します:
|
||||
|
||||
* `main`: `main.py`ファイル (Python "module")。
|
||||
* `app`: `main.py`内部で作られるobject(`app = FastAPI()`のように記述される)。
|
||||
* `--reload`: コードの変更時にサーバーを再起動させる。開発用。
|
||||
|
||||
///
|
||||
|
||||
出力には次のような行があります:
|
||||
|
||||
```hl_lines="4"
|
||||
@@ -40,7 +56,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
|
||||
この行はローカルマシンでアプリが提供されているURLを示しています。
|
||||
|
||||
### チェック
|
||||
### チェック { #check-it }
|
||||
|
||||
ブラウザで<a href="http://127.0.0.1:8000" class="external-link" target="_blank">http://127.0.0.1:8000</a>を開きます。
|
||||
|
||||
@@ -50,7 +66,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
{"message": "Hello World"}
|
||||
```
|
||||
|
||||
### 対話的APIドキュメント
|
||||
### 対話的APIドキュメント { #interactive-api-docs }
|
||||
|
||||
次に、<a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>にアクセスします。
|
||||
|
||||
@@ -58,7 +74,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
|
||||

|
||||
|
||||
### 他のAPIドキュメント
|
||||
### 代替APIドキュメント { #alternative-api-docs }
|
||||
|
||||
次に、<a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a>にアクセスします。
|
||||
|
||||
@@ -66,31 +82,31 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
|
||||

|
||||
|
||||
### OpenAPI
|
||||
### OpenAPI { #openapi }
|
||||
|
||||
**FastAPI**は、APIを定義するための**OpenAPI**標準規格を使用して、すべてのAPIの「スキーマ」を生成します。
|
||||
|
||||
#### 「スキーマ」
|
||||
#### 「スキーマ」 { #schema }
|
||||
|
||||
「スキーマ」は定義または説明です。実装コードではなく、単なる抽象的な説明です。
|
||||
|
||||
#### API「スキーマ」
|
||||
#### API「スキーマ」 { #api-schema }
|
||||
|
||||
ここでは、<a href="https://github.com/OAI/OpenAPI-Specification" class="external-link" target="_blank">OpenAPI</a>はAPIのスキーマ定義の方法を規定する仕様です。
|
||||
|
||||
このスキーマ定義はAPIパス、受け取り可能なパラメータなどが含まれます。
|
||||
|
||||
#### データ「スキーマ」
|
||||
#### データ「スキーマ」 { #data-schema }
|
||||
|
||||
「スキーマ」という用語は、JSONコンテンツなどの一部のデータの形状を指す場合もあります。
|
||||
|
||||
そのような場合、スキーマはJSON属性とそれらが持つデータ型などを意味します。
|
||||
|
||||
#### OpenAPIおよびJSONスキーマ
|
||||
#### OpenAPIおよびJSONスキーマ { #openapi-and-json-schema }
|
||||
|
||||
OpenAPIはAPIのためのAPIスキーマを定義します。そして、そのスキーマは**JSONデータスキーマ**の標準規格に準拠したJSONスキーマを利用するAPIによって送受されるデータの定義(または「スキーマ」)を含んでいます。
|
||||
|
||||
#### `openapi.json`を確認
|
||||
#### `openapi.json`を確認 { #check-the-openapi-json }
|
||||
|
||||
素のOpenAPIスキーマがどのようなものか興味がある場合、FastAPIはすべてのAPIの説明を含むJSON(スキーマ)を自動的に生成します。
|
||||
|
||||
@@ -100,7 +116,7 @@ OpenAPIはAPIのためのAPIスキーマを定義します。そして、その
|
||||
|
||||
```JSON
|
||||
{
|
||||
"openapi": "3.0.2",
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "FastAPI",
|
||||
"version": "0.1.0"
|
||||
@@ -119,7 +135,7 @@ OpenAPIはAPIのためのAPIスキーマを定義します。そして、その
|
||||
...
|
||||
```
|
||||
|
||||
#### OpenAPIの目的
|
||||
#### OpenAPIの目的 { #what-is-openapi-for }
|
||||
|
||||
OpenAPIスキーマは、FastAPIに含まれている2つのインタラクティブなドキュメントシステムの動力源です。
|
||||
|
||||
@@ -127,11 +143,47 @@ OpenAPIスキーマは、FastAPIに含まれている2つのインタラクテ
|
||||
|
||||
また、APIと通信するクライアント用のコードを自動的に生成するために使用することもできます。たとえば、フロントエンド、モバイル、またはIoTアプリケーションです。
|
||||
|
||||
## ステップ毎の要約
|
||||
### アプリをデプロイ(任意) { #deploy-your-app-optional }
|
||||
|
||||
### Step 1: `FastAPI`をインポート
|
||||
任意でFastAPIアプリを<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>にデプロイできます。まだなら、待機リストに登録してください。 🚀
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[1] *}
|
||||
すでに**FastAPI Cloud**アカウントがある場合(待機リストから招待済みの場合😉)、1コマンドでアプリケーションをデプロイできます。
|
||||
|
||||
デプロイする前に、ログインしていることを確認してください:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ fastapi login
|
||||
|
||||
You are logged in to FastAPI Cloud 🚀
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
その後、アプリをデプロイします:
|
||||
|
||||
<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でアプリにアクセスできます。 ✨
|
||||
|
||||
## ステップ毎の要約 { #recap-step-by-step }
|
||||
|
||||
### Step 1: `FastAPI`をインポート { #step-1-import-fastapi }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[1] *}
|
||||
|
||||
`FastAPI`は、APIのすべての機能を提供するPythonクラスです。
|
||||
|
||||
@@ -143,44 +195,16 @@ OpenAPIスキーマは、FastAPIに含まれている2つのインタラクテ
|
||||
|
||||
///
|
||||
|
||||
### Step 2: `FastAPI`の「インスタンス」を生成
|
||||
### Step 2: `FastAPI`の「インスタンス」を生成 { #step-2-create-a-fastapi-instance }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[3] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[3] *}
|
||||
ここで、`app`変数が`FastAPI`クラスの「インスタンス」になります。
|
||||
|
||||
これが、すべてのAPIを作成するための主要なポイントになります。
|
||||
|
||||
この`app`はコマンドで`uvicorn`が参照するものと同じです:
|
||||
### Step 3: *path operation*を作成 { #step-3-create-a-path-operation }
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
以下のようなアプリを作成したとき:
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial002.py hl[3] *}
|
||||
|
||||
そして、それを`main.py`ファイルに置き、次のように`uvicorn`を呼び出します:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:my_awesome_api --reload
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
### Step 3: *path operation*を作成
|
||||
|
||||
#### パス
|
||||
#### パス { #path }
|
||||
|
||||
ここでの「パス」とは、最初の`/`から始まるURLの最後の部分を指します。
|
||||
|
||||
@@ -204,7 +228,7 @@ https://example.com/items/foo
|
||||
|
||||
APIを構築する際、「パス」は「関心事」と「リソース」を分離するための主要な方法です。
|
||||
|
||||
#### Operation
|
||||
#### Operation { #operation }
|
||||
|
||||
ここでの「オペレーション」とは、HTTPの「メソッド」の1つを指します。
|
||||
|
||||
@@ -239,15 +263,16 @@ APIを構築するときは、通常、これらの特定のHTTPメソッドを
|
||||
|
||||
「**オペレーションズ**」とも呼ぶことにします。
|
||||
|
||||
#### *パスオペレーションデコレータ*を定義
|
||||
#### *path operation デコレータ*を定義 { #define-a-path-operation-decorator }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[6] *}
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[6] *}
|
||||
`@app.get("/")`は直下の関数が下記のリクエストの処理を担当することを**FastAPI**に伝えます:
|
||||
|
||||
* パス `/`
|
||||
* <abbr title="an HTTP GET method"><code>get</code> オペレーション</abbr>
|
||||
|
||||
/// info | `@decorator` について
|
||||
/// info | `@decorator` Info
|
||||
|
||||
Pythonにおける`@something`シンタックスはデコレータと呼ばれます。
|
||||
|
||||
@@ -255,9 +280,9 @@ Pythonにおける`@something`シンタックスはデコレータと呼ばれ
|
||||
|
||||
「デコレータ」は直下の関数を受け取り、それを使って何かを行います。
|
||||
|
||||
私たちの場合、このデコレーターは直下の関数が**オペレーション** `get`を使用した**パス**` / `に対応することを**FastAPI** に通知します。
|
||||
私たちの場合、このデコレーターは直下の関数が**オペレーション** `get`を使用した**パス** `/`に対応することを**FastAPI** に通知します。
|
||||
|
||||
これが「*パスオペレーションデコレータ*」です。
|
||||
これが「*path operation デコレータ*」です。
|
||||
|
||||
///
|
||||
|
||||
@@ -286,15 +311,15 @@ Pythonにおける`@something`シンタックスはデコレータと呼ばれ
|
||||
|
||||
///
|
||||
|
||||
### Step 4: **パスオペレーション**を定義
|
||||
### Step 4: **path operation 関数**を定義 { #step-4-define-the-path-operation-function }
|
||||
|
||||
以下は「**パスオペレーション関数**」です:
|
||||
以下は「**path operation 関数**」です:
|
||||
|
||||
* **パス**: は`/`です。
|
||||
* **オペレーション**: は`get`です。
|
||||
* **関数**: 「デコレータ」の直下にある関数 (`@app.get("/")`の直下) です。
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[7] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[7] *}
|
||||
|
||||
これは、Pythonの関数です。
|
||||
|
||||
@@ -306,28 +331,49 @@ Pythonにおける`@something`シンタックスはデコレータと呼ばれ
|
||||
|
||||
`async def`の代わりに通常の関数として定義することもできます:
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial003.py hl[7] *}
|
||||
{* ../../docs_src/first_steps/tutorial003_py39.py hl[7] *}
|
||||
|
||||
/// note | 備考
|
||||
|
||||
違いが分からない場合は、[Async: *"急いでいますか?"*](../async.md#_1){.internal-link target=_blank}を確認してください。
|
||||
違いが分からない場合は、[Async: *"急いでいますか?"*](../async.md#in-a-hurry){.internal-link target=_blank}を確認してください。
|
||||
|
||||
///
|
||||
|
||||
### Step 5: コンテンツの返信
|
||||
### Step 5: コンテンツの返信 { #step-5-return-the-content }
|
||||
|
||||
{* ../../docs_src/first_steps/tutorial001.py hl[8] *}
|
||||
{* ../../docs_src/first_steps/tutorial001_py39.py hl[8] *}
|
||||
|
||||
`dict`、`list`、`str`、`int`などを返すことができます。
|
||||
`dict`、`list`、`str`、`int`などの単一の値を返すことができます。
|
||||
|
||||
Pydanticモデルを返すこともできます(後で詳しく説明します)。
|
||||
|
||||
JSONに自動的に変換されるオブジェクトやモデルは他にもたくさんあります(ORMなど)。 お気に入りのものを使ってみてください。すでにサポートされている可能性が高いです。
|
||||
|
||||
## まとめ
|
||||
### Step 6: デプロイする { #step-6-deploy-it }
|
||||
|
||||
* `FastAPI`をインポート
|
||||
* `app`インスタンスを生成
|
||||
* **パスオペレーションデコレータ**を記述 (`@app.get("/")`)
|
||||
* **パスオペレーション関数**を定義 (上記の`def root(): ...`のように)
|
||||
* 開発サーバーを起動 (`uvicorn main:app --reload`)
|
||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>**に1コマンドでアプリをデプロイします: `fastapi deploy`. 🎉
|
||||
|
||||
#### FastAPI Cloudについて { #about-fastapi-cloud }
|
||||
|
||||
**<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a>**は、**FastAPI**の作者とそのチームによって開発されています。
|
||||
|
||||
最小限の労力でAPIの**構築**、**デプロイ**、**アクセス**を行うプロセスを合理化します。
|
||||
|
||||
FastAPIでアプリを構築するのと同じ**開発体験**を、クラウドへの**デプロイ**にもたらします。 🎉
|
||||
|
||||
FastAPI Cloudは、*FastAPI and friends*のオープンソースプロジェクトに対する主要スポンサーであり、資金提供元です。 ✨
|
||||
|
||||
#### 他のクラウドプロバイダにデプロイする { #deploy-to-other-cloud-providers }
|
||||
|
||||
FastAPIはオープンソースで、標準に基づいています。選択した任意のクラウドプロバイダにFastAPIアプリをデプロイできます。
|
||||
|
||||
クラウドプロバイダのガイドに従って、FastAPIアプリをデプロイしてください。 🤓
|
||||
|
||||
## まとめ { #recap }
|
||||
|
||||
* `FastAPI`をインポートします。
|
||||
* `app`インスタンスを生成します。
|
||||
* `@app.get("/")`のようなデコレータを使用して、**path operation デコレータ**を記述します。
|
||||
* **path operation 関数**を定義します。例: `def root(): ...`。
|
||||
* `fastapi dev`コマンドで開発サーバーを起動します。
|
||||
* 任意で`fastapi deploy`を使ってアプリをデプロイします。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# エラーハンドリング
|
||||
# エラーハンドリング { #handling-errors }
|
||||
|
||||
APIを使用しているクライアントにエラーを通知する必要がある状況はたくさんあります。
|
||||
|
||||
@@ -19,15 +19,15 @@ APIを使用しているクライアントにエラーを通知する必要が
|
||||
|
||||
**"404 Not Found"** のエラー(およびジョーク)を覚えていますか?
|
||||
|
||||
## `HTTPException`の使用
|
||||
## `HTTPException`の使用 { #use-httpexception }
|
||||
|
||||
HTTPレスポンスをエラーでクライアントに返すには、`HTTPException`を使用します。
|
||||
|
||||
### `HTTPException`のインポート
|
||||
### `HTTPException`のインポート { #import-httpexception }
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial001.py hl[1] *}
|
||||
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[1] *}
|
||||
|
||||
### コード内での`HTTPException`の発生
|
||||
### コード内での`HTTPException`の発生 { #raise-an-httpexception-in-your-code }
|
||||
|
||||
`HTTPException`は通常のPythonの例外であり、APIに関連するデータを追加したものです。
|
||||
|
||||
@@ -39,9 +39,9 @@ Pythonの例外なので、`return`ではなく、`raise`です。
|
||||
|
||||
この例では、クライアントが存在しないIDでアイテムを要求した場合、`404`のステータスコードを持つ例外を発生させます:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial001.py hl[11] *}
|
||||
{* ../../docs_src/handling_errors/tutorial001_py39.py hl[11] *}
|
||||
|
||||
### レスポンス結果
|
||||
### レスポンス結果 { #the-resulting-response }
|
||||
|
||||
クライアントが`http://example.com/items/foo`(`item_id` `"foo"`)をリクエストすると、HTTPステータスコードが200で、以下のJSONレスポンスが返されます:
|
||||
|
||||
@@ -69,7 +69,7 @@ Pythonの例外なので、`return`ではなく、`raise`です。
|
||||
|
||||
///
|
||||
|
||||
## カスタムヘッダーの追加
|
||||
## カスタムヘッダーの追加 { #add-custom-headers }
|
||||
|
||||
例えば、いくつかのタイプのセキュリティのために、HTTPエラーにカスタムヘッダを追加できると便利な状況がいくつかあります。
|
||||
|
||||
@@ -77,9 +77,9 @@ Pythonの例外なので、`return`ではなく、`raise`です。
|
||||
|
||||
しかし、高度なシナリオのために必要な場合には、カスタムヘッダーを追加することができます:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial002.py hl[14] *}
|
||||
{* ../../docs_src/handling_errors/tutorial002_py39.py hl[14] *}
|
||||
|
||||
## カスタム例外ハンドラのインストール
|
||||
## カスタム例外ハンドラのインストール { #install-custom-exception-handlers }
|
||||
|
||||
カスタム例外ハンドラは<a href="https://www.starlette.dev/exceptions/" class="external-link" target="_blank">Starletteと同じ例外ユーティリティ</a>を使用して追加することができます。
|
||||
|
||||
@@ -89,7 +89,7 @@ Pythonの例外なので、`return`ではなく、`raise`です。
|
||||
|
||||
カスタム例外ハンドラを`@app.exception_handler()`で追加することができます:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial003.py hl[5,6,7,13,14,15,16,17,18,24] *}
|
||||
{* ../../docs_src/handling_errors/tutorial003_py39.py hl[5:7,13:18,24] *}
|
||||
|
||||
ここで、`/unicorns/yolo`をリクエストすると、*path operation*は`UnicornException`を`raise`します。
|
||||
|
||||
@@ -109,7 +109,7 @@ Pythonの例外なので、`return`ではなく、`raise`です。
|
||||
|
||||
///
|
||||
|
||||
## デフォルトの例外ハンドラのオーバーライド
|
||||
## デフォルトの例外ハンドラのオーバーライド { #override-the-default-exception-handlers }
|
||||
|
||||
**FastAPI** にはいくつかのデフォルトの例外ハンドラがあります。
|
||||
|
||||
@@ -117,7 +117,7 @@ Pythonの例外なので、`return`ではなく、`raise`です。
|
||||
|
||||
これらの例外ハンドラを独自のものでオーバーライドすることができます。
|
||||
|
||||
### リクエスト検証の例外のオーバーライド
|
||||
### リクエスト検証の例外のオーバーライド { #override-request-validation-exceptions }
|
||||
|
||||
リクエストに無効なデータが含まれている場合、**FastAPI** は内部的に`RequestValidationError`を発生させます。
|
||||
|
||||
@@ -125,11 +125,11 @@ Pythonの例外なので、`return`ではなく、`raise`です。
|
||||
|
||||
これをオーバーライドするには`RequestValidationError`をインポートして`@app.exception_handler(RequestValidationError)`と一緒に使用して例外ハンドラをデコレートします。
|
||||
|
||||
この例外ハンドラは`Requset`と例外を受け取ります。
|
||||
この例外ハンドラは`Request`と例外を受け取ります。
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial004.py hl[2,14,15,16] *}
|
||||
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[2,14:19] *}
|
||||
|
||||
これで、`/items/foo`にアクセスすると、デフォルトのJSONエラーの代わりに以下が返されます:
|
||||
これで、`/items/foo`にアクセスすると、以下のデフォルトのJSONエラーの代わりに:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -146,39 +146,20 @@ Pythonの例外なので、`return`ではなく、`raise`です。
|
||||
}
|
||||
```
|
||||
|
||||
以下のようなテキスト版を取得します:
|
||||
以下のテキスト版を取得します:
|
||||
|
||||
```
|
||||
1 validation error
|
||||
path -> item_id
|
||||
value is not a valid integer (type=type_error.integer)
|
||||
Validation errors:
|
||||
Field: ('path', 'item_id'), Error: Input should be a valid integer, unable to parse string as an integer
|
||||
```
|
||||
|
||||
#### `RequestValidationError`と`ValidationError`
|
||||
|
||||
/// warning | 注意
|
||||
|
||||
これらは今のあなたにとって重要でない場合は省略しても良い技術的な詳細です。
|
||||
|
||||
///
|
||||
|
||||
`RequestValidationError`はPydanticの<a href="https://docs.pydantic.dev/latest/concepts/models/#error-handling" class="external-link" target="_blank">`ValidationError`</a>のサブクラスです。
|
||||
|
||||
**FastAPI** は`response_model`でPydanticモデルを使用していて、データにエラーがあった場合、ログにエラーが表示されるようにこれを使用しています。
|
||||
|
||||
しかし、クライアントやユーザーはそれを見ることはありません。その代わりに、クライアントはHTTPステータスコード`500`の「Internal Server Error」を受け取ります。
|
||||
|
||||
*レスポンス*やコードのどこか(クライアントの*リクエスト*ではなく)にPydanticの`ValidationError`がある場合、それは実際にはコードのバグなのでこのようにすべきです。
|
||||
|
||||
また、あなたがそれを修正している間は、セキュリティの脆弱性が露呈する場合があるため、クライアントやユーザーがエラーに関する内部情報にアクセスできないようにしてください。
|
||||
|
||||
### エラーハンドラ`HTTPException`のオーバーライド
|
||||
### `HTTPException`エラーハンドラのオーバーライド { #override-the-httpexception-error-handler }
|
||||
|
||||
同様に、`HTTPException`ハンドラをオーバーライドすることもできます。
|
||||
|
||||
例えば、これらのエラーに対しては、JSONではなくプレーンテキストを返すようにすることができます:
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial004.py hl[3,4,9,10,11,22] *}
|
||||
{* ../../docs_src/handling_errors/tutorial004_py39.py hl[3:4,9:11,25] *}
|
||||
|
||||
/// note | 技術詳細
|
||||
|
||||
@@ -188,13 +169,21 @@ path -> item_id
|
||||
|
||||
///
|
||||
|
||||
### `RequestValidationError`のボディの使用
|
||||
/// warning | 注意
|
||||
|
||||
`RequestValidationError`には、検証エラーが発生したファイル名と行番号の情報が含まれているため、必要であれば関連情報と一緒にログに表示できます。
|
||||
|
||||
しかし、そのまま文字列に変換して直接その情報を返すと、システムに関する情報が多少漏えいする可能性があります。そのため、ここではコードが各エラーを個別に抽出して表示します。
|
||||
|
||||
///
|
||||
|
||||
### `RequestValidationError`のボディの使用 { #use-the-requestvalidationerror-body }
|
||||
|
||||
`RequestValidationError`には無効なデータを含む`body`が含まれています。
|
||||
|
||||
アプリ開発中に本体のログを取ってデバッグしたり、ユーザーに返したりなどに使用することができます。
|
||||
アプリ開発中にボディのログを取ってデバッグしたり、ユーザーに返したりなどに使用することができます。
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial005.py hl[14] *}
|
||||
{* ../../docs_src/handling_errors/tutorial005_py39.py hl[14] *}
|
||||
|
||||
ここで、以下のような無効な項目を送信してみてください:
|
||||
|
||||
@@ -207,7 +196,7 @@ path -> item_id
|
||||
|
||||
受信したボディを含むデータが無効であることを示すレスポンスが表示されます:
|
||||
|
||||
```JSON hl_lines="12 13 14 15"
|
||||
```JSON hl_lines="12-15"
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
@@ -226,36 +215,30 @@ path -> item_id
|
||||
}
|
||||
```
|
||||
|
||||
#### FastAPIの`HTTPException`とStarletteの`HTTPException`
|
||||
#### FastAPIの`HTTPException`とStarletteの`HTTPException` { #fastapis-httpexception-vs-starlettes-httpexception }
|
||||
|
||||
**FastAPI**は独自の`HTTPException`を持っています。
|
||||
|
||||
また、 **FastAPI**のエラークラス`HTTPException`はStarletteのエラークラス`HTTPException`を継承しています。
|
||||
また、 **FastAPI**の`HTTPException`エラークラスはStarletteの`HTTPException`エラークラスを継承しています。
|
||||
|
||||
唯一の違いは、**FastAPI** の`HTTPException`はレスポンスに含まれるヘッダを追加できることです。
|
||||
|
||||
これはOAuth 2.0といくつかのセキュリティユーティリティのために内部的に必要とされ、使用されています。
|
||||
唯一の違いは、**FastAPI** の`HTTPException`は`detail`フィールドにJSONに変換可能な任意のデータを受け付けるのに対し、Starletteの`HTTPException`は文字列のみを受け付けることです。
|
||||
|
||||
そのため、コード内では通常通り **FastAPI** の`HTTPException`を発生させ続けることができます。
|
||||
|
||||
しかし、例外ハンドラを登録する際には、Starletteの`HTTPException`を登録しておく必要があります。
|
||||
しかし、例外ハンドラを登録する際には、Starletteの`HTTPException`に対して登録しておく必要があります。
|
||||
|
||||
これにより、Starletteの内部コードやStarletteの拡張機能やプラグインの一部が`HTTPException`を発生させた場合、ハンドラがそれをキャッチして処理することができるようになります。
|
||||
これにより、Starletteの内部コードやStarletteの拡張機能やプラグインの一部がStarletteの`HTTPException`を発生させた場合、ハンドラがそれをキャッチして処理できるようになります。
|
||||
|
||||
以下の例では、同じコード内で両方の`HTTPException`を使用できるようにするために、Starletteの例外の名前を`StarletteHTTPException`に変更しています:
|
||||
この例では、同じコード内で両方の`HTTPException`を使用できるようにするために、Starletteの例外を`StarletteHTTPException`にリネームしています:
|
||||
|
||||
```Python
|
||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||
```
|
||||
|
||||
### **FastAPI** の例外ハンドラの再利用
|
||||
### **FastAPI** の例外ハンドラの再利用 { #reuse-fastapis-exception-handlers }
|
||||
|
||||
また、何らかの方法で例外を使用することもできますが、**FastAPI** から同じデフォルトの例外ハンドラを使用することもできます。
|
||||
**FastAPI** から同じデフォルトの例外ハンドラと一緒に例外を使用したい場合は、`fastapi.exception_handlers`からデフォルトの例外ハンドラをインポートして再利用できます:
|
||||
|
||||
デフォルトの例外ハンドラを`fastapi.exception_handlers`からインポートして再利用することができます:
|
||||
{* ../../docs_src/handling_errors/tutorial006_py39.py hl[2:5,15,21] *}
|
||||
|
||||
{* ../../docs_src/handling_errors/tutorial006.py hl[2,3,4,5,15,21] *}
|
||||
|
||||
この例では、非常に表現力のあるメッセージでエラーを`print`しています。
|
||||
|
||||
しかし、例外を使用して、デフォルトの例外ハンドラを再利用することができるということが理解できます。
|
||||
この例では、非常に表現力のあるメッセージでエラーを`print`しているだけですが、要点は理解できるはずです。例外を使用し、その後デフォルトの例外ハンドラを再利用できます。
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
# ヘッダーのパラメータ
|
||||
# ヘッダーのパラメータ { #header-parameters }
|
||||
|
||||
ヘッダーのパラメータは、`Query`や`Path`、`Cookie`のパラメータを定義するのと同じように定義できます。
|
||||
|
||||
## `Header`をインポート
|
||||
## `Header`をインポート { #import-header }
|
||||
|
||||
まず、`Header`をインポートします:
|
||||
|
||||
{* ../../docs_src/header_params/tutorial001.py hl[3] *}
|
||||
{* ../../docs_src/header_params/tutorial001_an_py310.py hl[3] *}
|
||||
|
||||
## `Header`のパラメータの宣言
|
||||
## `Header`のパラメータの宣言 { #declare-header-parameters }
|
||||
|
||||
次に、`Path`や`Query`、`Cookie`と同じ構造を用いてヘッダーのパラメータを宣言します。
|
||||
|
||||
最初の値がデフォルト値で、追加の検証パラメータや注釈パラメータをすべて渡すことができます。
|
||||
デフォルト値に加えて、追加の検証パラメータや注釈パラメータをすべて定義できます:
|
||||
|
||||
{* ../../docs_src/header_params/tutorial001.py hl[9] *}
|
||||
{* ../../docs_src/header_params/tutorial001_an_py310.py hl[9] *}
|
||||
|
||||
/// note | 技術詳細
|
||||
|
||||
@@ -30,23 +30,23 @@
|
||||
|
||||
///
|
||||
|
||||
## 自動変換
|
||||
## 自動変換 { #automatic-conversion }
|
||||
|
||||
`Header`は`Path`や`Query`、`Cookie`が提供する機能に加え、少しだけ追加の機能を持っています。
|
||||
|
||||
ほとんどの標準ヘッダーは、「マイナス記号」(`-`)としても知られる「ハイフン」で区切られています。
|
||||
ほとんどの標準ヘッダーは、「マイナス記号」(`-`)としても知られる「ハイフン」文字で区切られています。
|
||||
|
||||
しかし、`user-agent`のような変数はPythonでは無効です。
|
||||
|
||||
そのため、デフォルトでは、`Header`はパラメータの文字をアンダースコア(`_`)からハイフン(`-`)に変換して、ヘッダーを抽出して文書化します。
|
||||
そのため、デフォルトでは、`Header`はパラメータ名の文字をアンダースコア(`_`)からハイフン(`-`)に変換して、ヘッダーを抽出して文書化します。
|
||||
|
||||
また、HTTPヘッダは大文字小文字を区別しないので、Pythonの標準スタイル(別名「スネークケース」)で宣言することができます。
|
||||
|
||||
そのため、`User_Agent`などのように最初の文字を大文字にする必要はなく、通常のPythonコードと同じように`user_agent`を使用することができます。
|
||||
|
||||
もしなんらかの理由でアンダースコアからハイフンへの自動変換を無効にする必要がある場合は、`Header`の`convert_underscores`に`False`を設定してください:
|
||||
もしなんらかの理由でアンダースコアからハイフンへの自動変換を無効にする必要がある場合は、`Header`のパラメータ`convert_underscores`を`False`に設定してください:
|
||||
|
||||
{* ../../docs_src/header_params/tutorial002.py hl[9] *}
|
||||
{* ../../docs_src/header_params/tutorial002_an_py310.py hl[10] *}
|
||||
|
||||
/// warning | 注意
|
||||
|
||||
@@ -54,26 +54,26 @@
|
||||
|
||||
///
|
||||
|
||||
## ヘッダーの重複
|
||||
## ヘッダーの重複 { #duplicate-headers }
|
||||
|
||||
受信したヘッダーが重複することがあります。つまり、同じヘッダーで複数の値を持つということです。
|
||||
|
||||
これらの場合、リストの型宣言を使用して定義することができます。
|
||||
これらの場合、型宣言でリストを使用して定義することができます。
|
||||
|
||||
重複したヘッダーのすべての値をPythonの`list`として受け取ることができます。
|
||||
|
||||
例えば、複数回出現する可能性のある`X-Token`のヘッダを定義するには、以下のように書くことができます:
|
||||
|
||||
{* ../../docs_src/header_params/tutorial003.py hl[9] *}
|
||||
{* ../../docs_src/header_params/tutorial003_an_py310.py hl[9] *}
|
||||
|
||||
もし、その*path operation*で通信する場合は、次のように2つのHTTPヘッダーを送信します:
|
||||
その*path operation*と通信する際に、次のように2つのHTTPヘッダーを送信する場合:
|
||||
|
||||
```
|
||||
X-Token: foo
|
||||
X-Token: bar
|
||||
```
|
||||
|
||||
このレスポンスは以下のようになります:
|
||||
レスポンスは以下のようになります:
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -84,8 +84,8 @@ X-Token: bar
|
||||
}
|
||||
```
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
ヘッダーは`Header`で宣言し、`Query`や`Path`、`Cookie`と同じパターンを使用する。
|
||||
ヘッダーは`Header`で宣言し、`Query`や`Path`、`Cookie`と同じ共通パターンを使用します。
|
||||
|
||||
また、変数のアンダースコアを気にする必要はありません。**FastAPI** がそれらの変換をすべて取り持ってくれます。
|
||||
|
||||
@@ -1,83 +1,95 @@
|
||||
# チュートリアル - ユーザーガイド
|
||||
# チュートリアル - ユーザーガイド { #tutorial-user-guide }
|
||||
|
||||
このチュートリアルは**FastAPI**のほぼすべての機能の使い方を段階的に紹介します。
|
||||
このチュートリアルでは、**FastAPI**のほとんどの機能を使う方法を段階的に紹介します。
|
||||
|
||||
各セクションは前のセクションを踏まえた内容になっています。しかし、トピックごとに分割されているので、特定のAPIの要求を満たすようなトピックに直接たどり着けるようになっています。
|
||||
各セクションは前のセクションを踏まえた内容になっています。しかし、トピックごとに分割されているので、特定のAPIのニーズを満たすために、任意の特定のトピックに直接進めるようになっています。
|
||||
|
||||
また、将来的にリファレンスとして機能するように構築されています。
|
||||
また、将来的にリファレンスとして機能するように構築されているので、後で戻ってきて必要なものを正確に確認できます。
|
||||
|
||||
従って、後でこのチュートリアルに戻ってきて必要なものを確認できます。
|
||||
|
||||
## コードを実行する
|
||||
## コードを実行する { #run-the-code }
|
||||
|
||||
すべてのコードブロックをコピーして直接使用できます(実際にテストされたPythonファイルです)。
|
||||
|
||||
いずれかの例を実行するには、コードを `main.py`ファイルにコピーし、` uvicorn`を次のように起動します:
|
||||
いずれかの例を実行するには、コードを `main.py`ファイルにコピーし、次のように `fastapi dev` を起動します:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
$ <font color="#4E9A06">fastapi</font> dev <u style="text-decoration-style:solid">main.py</u>
|
||||
|
||||
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
|
||||
<span style="color: green;">INFO</span>: Started reloader process [28720]
|
||||
<span style="color: green;">INFO</span>: Started server process [28722]
|
||||
<span style="color: green;">INFO</span>: Waiting for application startup.
|
||||
<span style="color: green;">INFO</span>: Application startup complete.
|
||||
<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">'/home/user/code/awesomeapp'</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の利点を本当に実感できます。
|
||||
|
||||
---
|
||||
|
||||
## FastAPIをインストールする
|
||||
## FastAPIをインストールする { #install-fastapi }
|
||||
|
||||
最初のステップは、FastAPIのインストールです。
|
||||
|
||||
チュートリアルのために、すべてのオプションの依存関係と機能をインストールしたいとき:
|
||||
[仮想環境](../virtual-environments.md){.internal-link target=_blank} を作成して有効化し、それから **FastAPIをインストール** してください:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install "fastapi[all]"
|
||||
$ pip install "fastapi[standard]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
...これには、コードを実行するサーバーとして使用できる `uvicorn`も含まれます。
|
||||
|
||||
/// note | 備考
|
||||
|
||||
パーツ毎にインストールすることも可能です。
|
||||
`pip install "fastapi[standard]"` でインストールすると、`fastapi-cloud-cli` を含むいくつかのデフォルトのオプション標準依存関係が付属します。これにより、<a href="https://fastapicloud.com" class="external-link" target="_blank">FastAPI Cloud</a> にデプロイできます。
|
||||
|
||||
以下は、アプリケーションを本番環境にデプロイする際に行うであろうものです:
|
||||
これらのオプション依存関係が不要な場合は、代わりに `pip install fastapi` をインストールできます。
|
||||
|
||||
```
|
||||
pip install fastapi
|
||||
```
|
||||
|
||||
また、サーバーとして動作するように`uvicorn` をインストールします:
|
||||
|
||||
```
|
||||
pip install "uvicorn[standard]"
|
||||
```
|
||||
|
||||
そして、使用したい依存関係をそれぞれ同様にインストールします。
|
||||
標準依存関係はインストールしたいが `fastapi-cloud-cli` は不要な場合は、`pip install "fastapi[standard-no-fastapi-cloud-cli]"` でインストールできます。
|
||||
|
||||
///
|
||||
|
||||
## 高度なユーザーガイド
|
||||
## 高度なユーザーガイド { #advanced-user-guide }
|
||||
|
||||
**高度なユーザーガイド**もあり、**チュートリアル - ユーザーガイド**の後で読むことができます。
|
||||
この **チュートリアル - ユーザーガイド** の後で、後から読める **高度なユーザーガイド** もあります。
|
||||
|
||||
**高度なユーザーガイド**は**チュートリアル - ユーザーガイド**に基づいており、同じ概念を使用し、いくつかの追加機能を紹介しています。
|
||||
**高度なユーザーガイド** は本チュートリアルをベースにしており、同じ概念を使用し、いくつかの追加機能を教えます。
|
||||
|
||||
ただし、最初に**チュートリアル - ユーザーガイド**(現在読んでいる内容)をお読みください。
|
||||
ただし、最初に **チュートリアル - ユーザーガイド**(今読んでいる内容)をお読みください。
|
||||
|
||||
**チュートリアル-ユーザーガイド**だけで完全なアプリケーションを構築できるように設計されています。加えて、**高度なユーザーガイド**の中からニーズに応じたアイデアを使用して、様々な拡張が可能です。
|
||||
**チュートリアル - ユーザーガイド** だけで完全なアプリケーションを構築できるように設計されており、その後ニーズに応じて、**高度なユーザーガイド** の追加のアイデアのいくつかを使って、さまざまな方法で拡張できます。
|
||||
|
||||
@@ -1,47 +1,66 @@
|
||||
# メタデータとドキュメントのURL
|
||||
# メタデータとドキュメントのURL { #metadata-and-docs-urls }
|
||||
|
||||
**FastAPI** アプリケーションのいくつかのメタデータの設定をカスタマイズできます。
|
||||
**FastAPI** アプリケーションのいくつかのメタデータ設定をカスタマイズできます。
|
||||
|
||||
## タイトル、説明文、バージョン
|
||||
## APIのメタデータ { #metadata-for-api }
|
||||
|
||||
以下を設定できます:
|
||||
OpenAPI仕様および自動APIドキュメントUIで使用される次のフィールドを設定できます:
|
||||
|
||||
* **タイトル**: OpenAPIおよび自動APIドキュメントUIでAPIのタイトル/名前として使用される。
|
||||
* **説明文**: OpenAPIおよび自動APIドキュメントUIでのAPIの説明文。
|
||||
* **バージョン**: APIのバージョン。例: `v2` または `2.5.0`。
|
||||
*たとえば、以前のバージョンのアプリケーションがあり、OpenAPIも使用している場合に便利です。
|
||||
| パラメータ | 型 | 説明 |
|
||||
|------------|------|-------------|
|
||||
| `title` | `str` | APIのタイトルです。 |
|
||||
| `summary` | `str` | APIの短い要約です。 <small>OpenAPI 3.1.0、FastAPI 0.99.0 以降で利用できます。</small> |
|
||||
| `description` | `str` | APIの短い説明です。Markdownを使用できます。 |
|
||||
| `version` | `string` | APIのバージョンです。これはOpenAPIのバージョンではなく、あなた自身のアプリケーションのバージョンです。たとえば `2.5.0` です。 |
|
||||
| `terms_of_service` | `str` | APIの利用規約へのURLです。指定する場合、URLである必要があります。 |
|
||||
| `contact` | `dict` | 公開されるAPIの連絡先情報です。複数のフィールドを含められます。 <details><summary><code>contact</code> fields</summary><table><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td>連絡先の個人/組織を識別する名前です。</td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>連絡先情報を指すURLです。URL形式である必要があります。</td></tr><tr><td><code>email</code></td><td><code>str</code></td><td>連絡先の個人/組織のメールアドレスです。メールアドレス形式である必要があります。</td></tr></tbody></table></details> |
|
||||
| `license_info` | `dict` | 公開されるAPIのライセンス情報です。複数のフィールドを含められます。 <details><summary><code>license_info</code> fields</summary><table><thead><tr><th>Parameter</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>name</code></td><td><code>str</code></td><td><strong>必須</strong>(<code>license_info</code> が設定されている場合)。APIに使用されるライセンス名です。</td></tr><tr><td><code>identifier</code></td><td><code>str</code></td><td>APIの <a href="https://spdx.org/licenses/" class="external-link" target="_blank">SPDX</a> ライセンス式です。<code>identifier</code> フィールドは <code>url</code> フィールドと同時に指定できません。 <small>OpenAPI 3.1.0、FastAPI 0.99.0 以降で利用できます。</small></td></tr><tr><td><code>url</code></td><td><code>str</code></td><td>APIに使用されるライセンスへのURLです。URL形式である必要があります。</td></tr></tbody></table></details> |
|
||||
|
||||
これらを設定するには、パラメータ `title`、`description`、`version` を使用します:
|
||||
以下のように設定できます:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial001.py hl[4:6] *}
|
||||
{* ../../docs_src/metadata/tutorial001_py39.py hl[3:16, 19:32] *}
|
||||
|
||||
この設定では、自動APIドキュメントは以下の様になります:
|
||||
/// tip | 豆知識
|
||||
|
||||
`description` フィールドにはMarkdownを書けて、出力ではレンダリングされます。
|
||||
|
||||
///
|
||||
|
||||
この設定では、自動APIドキュメントは以下のようになります:
|
||||
|
||||
<img src="/img/tutorial/metadata/image01.png">
|
||||
|
||||
## タグのためのメタデータ
|
||||
## ライセンス識別子 { #license-identifier }
|
||||
|
||||
さらに、パラメータ `openapi_tags` を使うと、path operations をグループ分けするための複数のタグに関するメタデータを追加できます。
|
||||
OpenAPI 3.1.0 および FastAPI 0.99.0 以降では、`license_info` を `url` の代わりに `identifier` で設定することもできます。
|
||||
|
||||
それぞれのタグ毎にひとつの辞書を含むリストをとります。
|
||||
例:
|
||||
|
||||
それぞれの辞書は以下をもつことができます:
|
||||
{* ../../docs_src/metadata/tutorial001_1_py39.py hl[31] *}
|
||||
|
||||
* `name` (**必須**): *path operations* および `APIRouter` の `tags` パラメーターで使用するのと同じタグ名である `str`。
|
||||
* `description`: タグの簡単な説明文である `str`。 Markdownで記述でき、ドキュメントUIに表示されます。
|
||||
* `externalDocs`: 外部ドキュメントを説明するための `dict`:
|
||||
* `description`: 外部ドキュメントの簡単な説明文である `str`。
|
||||
* `url` (**必須**): 外部ドキュメントのURLである `str`。
|
||||
## タグのメタデータ { #metadata-for-tags }
|
||||
|
||||
### タグのためのメタデータの作成
|
||||
パラメータ `openapi_tags` を使うと、path operation をグループ分けするために使用する各タグに追加のメタデータを追加できます。
|
||||
|
||||
`users` と `items` のタグを使った例でメタデータの追加を試してみましょう。
|
||||
それぞれのタグごとに1つの辞書を含むリストを取ります。
|
||||
|
||||
タグのためのメタデータを作成し、それを `openapi_tags` パラメータに渡します。
|
||||
それぞれの辞書は以下を含められます:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial004.py hl[3:16,18] *}
|
||||
* `name` (**必須**): *path operation* および `APIRouter` の `tags` パラメータで使用するのと同じタグ名の `str`。
|
||||
* `description`: タグの短い説明の `str`。Markdownを含められ、ドキュメントUIに表示されます。
|
||||
* `externalDocs`: 外部ドキュメントを説明する `dict`。以下を含みます:
|
||||
* `description`: 外部ドキュメントの短い説明の `str`。
|
||||
* `url` (**必須**): 外部ドキュメントのURLの `str`。
|
||||
|
||||
説明文 (description) の中で Markdown を使用できることに注意してください。たとえば、「login」は太字 (**login**) で表示され、「fancy」は斜体 (_fancy_) で表示されます。
|
||||
### タグのメタデータの作成 { #create-metadata-for-tags }
|
||||
|
||||
`users` と `items` のタグを使った例で試してみましょう。
|
||||
|
||||
タグのメタデータを作成し、それを `openapi_tags` パラメータに渡します:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial004_py39.py hl[3:16,18] *}
|
||||
|
||||
説明の中でMarkdownを使用できることに注意してください。たとえば「login」は太字 (**login**) で表示され、「fancy」は斜体 (_fancy_) で表示されます。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
@@ -49,31 +68,31 @@
|
||||
|
||||
///
|
||||
|
||||
### 自作タグの使用
|
||||
### タグの使用 { #use-your-tags }
|
||||
|
||||
`tags` パラメーターを使用して、それぞれの *path operations* (および `APIRouter`) を異なるタグに割り当てます:
|
||||
*path operation*(および `APIRouter`)の `tags` パラメータを使用して、それらを異なるタグに割り当てます:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial004.py hl[21,26] *}
|
||||
{* ../../docs_src/metadata/tutorial004_py39.py hl[21,26] *}
|
||||
|
||||
/// info | 情報
|
||||
|
||||
タグのより詳しい説明を知りたい場合は [Path Operation Configuration](path-operation-configuration.md#tags){.internal-link target=_blank} を参照して下さい。
|
||||
タグの詳細は [Path Operation Configuration](path-operation-configuration.md#tags){.internal-link target=_blank} を参照してください。
|
||||
|
||||
///
|
||||
|
||||
### ドキュメントの確認
|
||||
### ドキュメントの確認 { #check-the-docs }
|
||||
|
||||
ここで、ドキュメントを確認すると、追加したメタデータがすべて表示されます:
|
||||
ここでドキュメントを確認すると、追加したメタデータがすべて表示されます:
|
||||
|
||||
<img src="/img/tutorial/metadata/image02.png">
|
||||
|
||||
### タグの順番
|
||||
### タグの順番 { #order-of-tags }
|
||||
|
||||
タグのメタデータ辞書の順序は、ドキュメントUIに表示される順序の定義にもなります。
|
||||
|
||||
たとえば、`users` はアルファベット順では `items` の後に続きます。しかし、リストの最初に `users` のメタデータ辞書を追加したため、ドキュメントUIでは `users` が先に表示されます。
|
||||
たとえば、`users` はアルファベット順では `items` の後に続きますが、リストの最初の辞書としてメタデータを追加したため、それより前に表示されます。
|
||||
|
||||
## OpenAPI URL
|
||||
## OpenAPI URL { #openapi-url }
|
||||
|
||||
デフォルトでは、OpenAPIスキーマは `/openapi.json` で提供されます。
|
||||
|
||||
@@ -81,21 +100,21 @@
|
||||
|
||||
たとえば、`/api/v1/openapi.json` で提供されるように設定するには:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial002.py hl[3] *}
|
||||
{* ../../docs_src/metadata/tutorial002_py39.py hl[3] *}
|
||||
|
||||
OpenAPIスキーマを完全に無効にする場合は、`openapi_url=None` を設定できます。これにより、それを使用するドキュメントUIも無効になります。
|
||||
|
||||
## ドキュメントのURL
|
||||
## ドキュメントのURL { #docs-urls }
|
||||
|
||||
以下の2つのドキュメントUIを構築できます:
|
||||
含まれている2つのドキュメントUIを設定できます:
|
||||
|
||||
* **Swagger UI**: `/docs` で提供されます。
|
||||
* URL はパラメータ `docs_url` で設定できます。
|
||||
* `docs_url=None` を設定することで無効にできます。
|
||||
* ReDoc: `/redoc` で提供されます。
|
||||
* URL はパラメータ `redoc_url` で設定できます。
|
||||
* `redoc_url=None` を設定することで無効にできます。
|
||||
* URL はパラメータ `docs_url` で設定できます。
|
||||
* `docs_url=None` を設定することで無効にできます。
|
||||
* **ReDoc**: `/redoc` で提供されます。
|
||||
* URL はパラメータ `redoc_url` で設定できます。
|
||||
* `redoc_url=None` を設定することで無効にできます。
|
||||
|
||||
たとえば、`/documentation` でSwagger UIが提供されるように設定し、ReDocを無効にするには:
|
||||
|
||||
{* ../../docs_src/metadata/tutorial003.py hl[3] *}
|
||||
{* ../../docs_src/metadata/tutorial003_py39.py hl[3] *}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# ミドルウェア
|
||||
# ミドルウェア { #middleware }
|
||||
|
||||
**FastAPI** アプリケーションにミドルウェアを追加できます。
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
|
||||
`yield` を使った依存関係をもつ場合は、終了コードはミドルウェアの *後に* 実行されます。
|
||||
|
||||
バックグラウンドタスク (後述) がある場合は、それらは全てのミドルウェアの *後に* 実行されます。
|
||||
バックグラウンドタスク ([バックグラウンドタスク](background-tasks.md){.internal-link target=_blank} セクションで説明します。後で確認できます) がある場合は、それらは全てのミドルウェアの *後に* 実行されます。
|
||||
|
||||
///
|
||||
|
||||
## ミドルウェアの作成
|
||||
## ミドルウェアの作成 { #create-a-middleware }
|
||||
|
||||
ミドルウェアを作成するには、関数の上部でデコレータ `@app.middleware("http")` を使用します。
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
* 次に、対応する*path operation*によって生成された `response` を返します。
|
||||
* その後、`response` を返す前にさらに `response` を変更することもできます。
|
||||
|
||||
{* ../../docs_src/middleware/tutorial001.py hl[8:9,11,14] *}
|
||||
{* ../../docs_src/middleware/tutorial001_py39.py hl[8:9,11,14] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">'X-'プレフィックスを使用</a>してカスタムの独自ヘッダーを追加できます。
|
||||
カスタムの独自ヘッダーは <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers" class="external-link" target="_blank">`X-` プレフィックスを使用</a>して追加できる点に注意してください。
|
||||
|
||||
ただし、ブラウザのクライアントに表示させたいカスタムヘッダーがある場合は、<a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">StarletteのCORSドキュメント</a>に記載されているパラメータ `expose_headers` を使用して、それらをCORS設定に追加する必要があります ([CORS (オリジン間リソース共有)](cors.md){.internal-link target=_blank})
|
||||
ただし、ブラウザのクライアントに表示させたいカスタムヘッダーがある場合は、<a href="https://www.starlette.dev/middleware/#corsmiddleware" class="external-link" target="_blank">StarletteのCORSドキュメント</a>に記載されているパラメータ `expose_headers` を使用して、それらをCORS設定に追加する必要があります ([CORS (Cross-Origin Resource Sharing)](cors.md){.internal-link target=_blank})。
|
||||
|
||||
///
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
///
|
||||
|
||||
### `response` の前後
|
||||
### `response` の前後 { #before-and-after-the-response }
|
||||
|
||||
*path operation* が `request` を受け取る前に、 `request` とともに実行されるコードを追加できます。
|
||||
|
||||
@@ -57,9 +57,38 @@
|
||||
|
||||
例えば、リクエストの処理とレスポンスの生成にかかった秒数を含むカスタムヘッダー `X-Process-Time` を追加できます:
|
||||
|
||||
{* ../../docs_src/middleware/tutorial001.py hl[10,12:13] *}
|
||||
{* ../../docs_src/middleware/tutorial001_py39.py hl[10,12:13] *}
|
||||
|
||||
## その他のミドルウェア
|
||||
/// tip | 豆知識
|
||||
|
||||
ここでは、これらのユースケースに対してより正確になり得るため、`time.time()` の代わりに <a href="https://docs.python.org/3/library/time.html#time.perf_counter" class="external-link" target="_blank">`time.perf_counter()`</a> を使用しています。 🤓
|
||||
|
||||
///
|
||||
|
||||
## 複数ミドルウェアの実行順序 { #multiple-middleware-execution-order }
|
||||
|
||||
`@app.middleware()` デコレータまたは `app.add_middleware()` メソッドのいずれかを使って複数のミドルウェアを追加すると、新しく追加された各ミドルウェアがアプリケーションをラップし、スタックを形成します。最後に追加されたミドルウェアが *最も外側*、最初に追加されたミドルウェアが *最も内側* になります。
|
||||
|
||||
リクエスト経路では、*最も外側* のミドルウェアが最初に実行されます。
|
||||
|
||||
レスポンス経路では、最後に実行されます。
|
||||
|
||||
例:
|
||||
|
||||
```Python
|
||||
app.add_middleware(MiddlewareA)
|
||||
app.add_middleware(MiddlewareB)
|
||||
```
|
||||
|
||||
これにより、実行順序は次のようになります:
|
||||
|
||||
* **リクエスト**: MiddlewareB → MiddlewareA → route
|
||||
|
||||
* **レスポンス**: route → MiddlewareA → MiddlewareB
|
||||
|
||||
このスタック動作により、ミドルウェアが予測可能で制御しやすい順序で実行されることが保証されます。
|
||||
|
||||
## その他のミドルウェア { #other-middlewares }
|
||||
|
||||
他のミドルウェアの詳細については、[高度なユーザーガイド: 高度なミドルウェア](../advanced/middleware.md){.internal-link target=_blank}を参照してください。
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Path Operationの設定
|
||||
# Path Operationの設定 { #path-operation-configuration }
|
||||
|
||||
*path operationデコレータ*を設定するためのパラメータがいくつかあります。
|
||||
|
||||
/// warning | 注意
|
||||
|
||||
これらのパラメータは*path operation関数*ではなく、*path operationデコレータ*に直接渡されることに注意してください。
|
||||
これらのパラメータは*path operationデコレータ*に直接渡され、*path operation関数*に渡されないことに注意してください。
|
||||
|
||||
///
|
||||
|
||||
## レスポンスステータスコード
|
||||
## レスポンスステータスコード { #response-status-code }
|
||||
|
||||
*path operation*のレスポンスで使用する(HTTP)`status_code`を定義することができます。
|
||||
|
||||
@@ -16,55 +16,65 @@
|
||||
|
||||
しかし、それぞれの番号コードが何のためのものか覚えていない場合は、`status`のショートカット定数を使用することができます:
|
||||
|
||||
{* ../../docs_src/path_operation_configuration/tutorial001.py hl[3,17] *}
|
||||
{* ../../docs_src/path_operation_configuration/tutorial001_py310.py hl[1,15] *}
|
||||
|
||||
そのステータスコードはレスポンスで使用され、OpenAPIスキーマに追加されます。
|
||||
|
||||
/// note | 技術詳細
|
||||
|
||||
また、`from starlette import status`を使用することもできます。
|
||||
`from starlette import status`を使用することもできます。
|
||||
|
||||
**FastAPI** は開発者の利便性を考慮して、`fastapi.status`と同じ`starlette.status`を提供しています。しかし、これはStarletteから直接提供されています。
|
||||
|
||||
///
|
||||
|
||||
## タグ
|
||||
## タグ { #tags }
|
||||
|
||||
`tags`パラメータを`str`の`list`(通常は1つの`str`)と一緒に渡すと、*path operation*にタグを追加できます:
|
||||
|
||||
{* ../../docs_src/path_operation_configuration/tutorial002.py hl[17,22,27] *}
|
||||
{* ../../docs_src/path_operation_configuration/tutorial002_py310.py hl[15,20,25] *}
|
||||
|
||||
これらはOpenAPIスキーマに追加され、自動ドキュメントのインターフェースで使用されます:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/path-operation-configuration/image01.png">
|
||||
<img src="/img/tutorial/path-operation-configuration/image01.png">
|
||||
|
||||
## 概要と説明
|
||||
### Enumを使ったタグ { #tags-with-enums }
|
||||
|
||||
大きなアプリケーションの場合、**複数のタグ**が蓄積されていき、関連する*path operations*に対して常に**同じタグ**を使っていることを確認したくなるかもしれません。
|
||||
|
||||
このような場合、タグを`Enum`に格納すると理にかなっています。
|
||||
|
||||
**FastAPI** は、プレーンな文字列の場合と同じ方法でそれをサポートしています:
|
||||
|
||||
{* ../../docs_src/path_operation_configuration/tutorial002b_py39.py hl[1,8:10,13,18] *}
|
||||
|
||||
## 概要と説明 { #summary-and-description }
|
||||
|
||||
`summary`と`description`を追加できます:
|
||||
|
||||
{* ../../docs_src/path_operation_configuration/tutorial003.py hl[20:21] *}
|
||||
{* ../../docs_src/path_operation_configuration/tutorial003_py310.py hl[17:18] *}
|
||||
|
||||
## docstringを用いた説明
|
||||
## docstringを用いた説明 { #description-from-docstring }
|
||||
|
||||
説明文は長くて複数行におよぶ傾向があるので、関数<abbr title="ドキュメントに使用される関数内の最初の式(変数に代入されていない)としての複数行の文字列">docstring</abbr>内に*path operation*の説明文を宣言できます。すると、**FastAPI** は説明文を読み込んでくれます。
|
||||
説明文は長くて複数行におよぶ傾向があるので、関数<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** は説明文を読み込んでくれます。
|
||||
|
||||
docstringに<a href="https://en.wikipedia.org/wiki/Markdown" class="external-link" target="_blank">Markdown</a>を記述すれば、正しく解釈されて表示されます。(docstringのインデントを考慮して)
|
||||
|
||||
{* ../../docs_src/path_operation_configuration/tutorial004.py hl[19:27] *}
|
||||
{* ../../docs_src/path_operation_configuration/tutorial004_py310.py hl[17:25] *}
|
||||
|
||||
これは対話的ドキュメントで使用されます:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/path-operation-configuration/image02.png">
|
||||
<img src="/img/tutorial/path-operation-configuration/image02.png">
|
||||
|
||||
## レスポンスの説明
|
||||
## レスポンスの説明 { #response-description }
|
||||
|
||||
`response_description`パラメータでレスポンスの説明をすることができます。
|
||||
|
||||
{* ../../docs_src/path_operation_configuration/tutorial005.py hl[21] *}
|
||||
{* ../../docs_src/path_operation_configuration/tutorial005_py310.py hl[18] *}
|
||||
|
||||
/// info | 情報
|
||||
|
||||
`respnse_description`は具体的にレスポンスを参照し、`description`は*path operation*全般を参照していることに注意してください。
|
||||
`response_description`は具体的にレスポンスを参照し、`description`は*path operation*全般を参照していることに注意してください。
|
||||
|
||||
///
|
||||
|
||||
@@ -76,22 +86,22 @@ OpenAPIは*path operation*ごとにレスポンスの説明を必要としてい
|
||||
|
||||
///
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/path-operation-configuration/image03.png">
|
||||
<img src="/img/tutorial/path-operation-configuration/image03.png">
|
||||
|
||||
## 非推奨の*path operation*
|
||||
## *path operation*を非推奨にする { #deprecate-a-path-operation }
|
||||
|
||||
*path operation*を<abbr title="非推奨、使わない方がよい">deprecated</abbr>としてマークする必要があるが、それを削除しない場合は、`deprecated`パラメータを渡します:
|
||||
*path operation*を<abbr title="obsolete, recommended not to use it – 非推奨、使わない方がよい">deprecated</abbr>としてマークする必要があるが、それを削除しない場合は、`deprecated`パラメータを渡します:
|
||||
|
||||
{* ../../docs_src/path_operation_configuration/tutorial006.py hl[16] *}
|
||||
{* ../../docs_src/path_operation_configuration/tutorial006_py39.py hl[16] *}
|
||||
|
||||
対話的ドキュメントでは非推奨と明記されます:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/path-operation-configuration/image04.png">
|
||||
<img src="/img/tutorial/path-operation-configuration/image04.png">
|
||||
|
||||
*path operations*が非推奨である場合とそうでない場合でどのように見えるかを確認してください:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/path-operation-configuration/image05.png">
|
||||
<img src="/img/tutorial/path-operation-configuration/image05.png">
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
*path operationデコレータ*にパラメータを渡すことで、*path operations*のメタデータを簡単に設定・追加することができます。
|
||||
|
||||
@@ -1,40 +1,52 @@
|
||||
# パスパラメータと数値の検証
|
||||
# パスパラメータと数値の検証 { #path-parameters-and-numeric-validations }
|
||||
|
||||
クエリパラメータに対して`Query`でより多くのバリデーションとメタデータを宣言できるのと同じように、パスパラメータに対しても`Path`で同じ種類のバリデーションとメタデータを宣言することができます。
|
||||
|
||||
## Pathのインポート
|
||||
## `Path`のインポート { #import-path }
|
||||
|
||||
まず初めに、`fastapi`から`Path`をインポートします:
|
||||
まず初めに、`fastapi`から`Path`をインポートし、`Annotated`もインポートします:
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial001.py hl[1] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[1,3] *}
|
||||
|
||||
## メタデータの宣言
|
||||
/// info | 情報
|
||||
|
||||
FastAPI はバージョン 0.95.0 で`Annotated`のサポートを追加し(そして推奨し始めました)。
|
||||
|
||||
古いバージョンの場合、`Annotated`を使おうとするとエラーになります。
|
||||
|
||||
`Annotated`を使用する前に、FastAPI のバージョンを少なくとも 0.95.1 まで[アップグレードしてください](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}。
|
||||
|
||||
///
|
||||
|
||||
## メタデータの宣言 { #declare-metadata }
|
||||
|
||||
パラメータは`Query`と同じものを宣言することができます。
|
||||
|
||||
例えば、パスパラメータ`item_id`に対して`title`のメタデータを宣言するには以下のようにします:
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial001.py hl[8] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial001_an_py310.py hl[10] *}
|
||||
|
||||
/// note | 備考
|
||||
|
||||
パスの一部でなければならないので、パスパラメータは常に必須です。
|
||||
|
||||
そのため、`...`を使用して必須と示す必要があります。
|
||||
|
||||
それでも、`None`で宣言しても、デフォルト値を設定しても、何の影響もなく、常に必要とされていることに変わりはありません。
|
||||
パスパラメータはパスの一部でなければならないので、常に必須です。`None`で宣言したりデフォルト値を設定したりしても何も影響せず、常に必須のままです。
|
||||
|
||||
///
|
||||
|
||||
## 必要に応じてパラメータを並び替える
|
||||
## 必要に応じてパラメータを並び替える { #order-the-parameters-as-you-need }
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
`Annotated`を使う場合、これはおそらくそれほど重要でも必要でもありません。
|
||||
|
||||
///
|
||||
|
||||
クエリパラメータ`q`を必須の`str`として宣言したいとしましょう。
|
||||
|
||||
また、このパラメータには何も宣言する必要がないので、`Query`を使う必要はありません。
|
||||
|
||||
しかし、パスパラメータ`item_id`のために`Path`を使用する必要があります。
|
||||
しかし、パスパラメータ`item_id`のために`Path`を使用する必要があります。そして何らかの理由で`Annotated`を使いたくないとします。
|
||||
|
||||
Pythonは「デフォルト」を持たない値の前に「デフォルト」を持つ値を置くことができません。
|
||||
Pythonは「デフォルト」を持つ値を「デフォルト」を持たない値の前に置くとエラーになります。
|
||||
|
||||
しかし、それらを並び替えることができ、デフォルト値を持たない値(クエリパラメータ`q`)を最初に持つことができます。
|
||||
|
||||
@@ -42,63 +54,88 @@ Pythonは「デフォルト」を持たない値の前に「デフォルト」
|
||||
|
||||
そのため、以下のように関数を宣言することができます:
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial002.py hl[8] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial002_py39.py hl[7] *}
|
||||
|
||||
## 必要に応じてパラメータを並び替えるトリック
|
||||
ただし、`Annotated`を使う場合はこの問題は起きないことを覚えておいてください。`Query()`や`Path()`に関数パラメータのデフォルト値を使わないためです。
|
||||
|
||||
クエリパラメータ`q`を`Query`やデフォルト値なしで宣言し、パスパラメータ`item_id`を`Path`を用いて宣言し、それらを別の順番に並びたい場合、Pythonには少し特殊な構文が用意されています。
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial002_an_py39.py *}
|
||||
|
||||
## 必要に応じてパラメータを並び替えるトリック { #order-the-parameters-as-you-need-tricks }
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
`Annotated`を使う場合、これはおそらくそれほど重要でも必要でもありません。
|
||||
|
||||
///
|
||||
|
||||
これは**小さなトリック**で、便利な場合がありますが、頻繁に必要になることはありません。
|
||||
|
||||
次のことをしたい場合:
|
||||
|
||||
* `q`クエリパラメータを`Query`もデフォルト値もなしで宣言する
|
||||
* パスパラメータ`item_id`を`Path`を使って宣言する
|
||||
* それらを別の順番にする
|
||||
* `Annotated`を使わない
|
||||
|
||||
...Pythonにはそのための少し特殊な構文があります。
|
||||
|
||||
関数の最初のパラメータとして`*`を渡します。
|
||||
|
||||
Pythonはその`*`で何かをすることはありませんが、それ以降のすべてのパラメータがキーワード引数(キーと値のペア)として呼ばれるべきものであると知っているでしょう。それは<abbr title="From: K-ey W-ord Arg-uments"><code>kwargs</code></abbr>としても知られています。たとえデフォルト値がなくても。
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial003.py hl[8] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial003_py39.py hl[7] *}
|
||||
|
||||
## 数値の検証: 以上
|
||||
### `Annotated`のほうがよい { #better-with-annotated }
|
||||
|
||||
`Query`と`Path`(、そして後述する他のもの)を用いて、文字列の制約を宣言することができますが、数値の制約も同様に宣言できます。
|
||||
`Annotated`を使う場合は、関数パラメータのデフォルト値を使わないため、この問題は起きず、おそらく`*`を使う必要もありません。
|
||||
|
||||
ここで、`ge=1`の場合、`item_id`は`1`「より大きい`g`か、同じ`e`」整数でなれけばなりません。
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial003_an_py39.py hl[10] *}
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial004.py hl[8] *}
|
||||
## 数値の検証: 以上 { #number-validations-greater-than-or-equal }
|
||||
|
||||
## 数値の検証: より大きいと小なりイコール
|
||||
`Query`と`Path`(、そして後述する他のもの)を用いて、数値の制約を宣言できます。
|
||||
|
||||
ここで、`ge=1`の場合、`item_id`は`1`「より大きい`g`か、同じ`e`」整数でなければなりません。
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial004_an_py39.py hl[10] *}
|
||||
|
||||
## 数値の検証: より大きいと小なりイコール { #number-validations-greater-than-and-less-than-or-equal }
|
||||
|
||||
以下も同様です:
|
||||
|
||||
* `gt`: より大きい(`g`reater `t`han)
|
||||
* `le`: 小なりイコール(`l`ess than or `e`qual)
|
||||
* `gt`: `g`reater `t`han
|
||||
* `le`: `l`ess than or `e`qual
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial005.py hl[9] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial005_an_py39.py hl[10] *}
|
||||
|
||||
## 数値の検証: 浮動小数点、 大なり小なり
|
||||
## 数値の検証: 浮動小数点、 大なり小なり { #number-validations-floats-greater-than-and-less-than }
|
||||
|
||||
数値のバリデーションは`float`の値に対しても有効です。
|
||||
|
||||
ここで重要になってくるのは<abbr title="より大きい"><code>gt</code></abbr>だけでなく<abbr title="以下"><code>ge</code></abbr>も宣言できることです。これと同様に、例えば、値が`1`より小さくても`0`より大きくなければならないことを要求することができます。
|
||||
ここで重要になってくるのは<abbr title="greater than – より大きい"><code>gt</code></abbr>だけでなく<abbr title="greater than or equal – 以上"><code>ge</code></abbr>も宣言できることです。これと同様に、例えば、値が`1`より小さくても`0`より大きくなければならないことを要求することができます。
|
||||
|
||||
したがって、`0.5`は有効な値ですが、`0.0`や`0`はそうではありません。
|
||||
|
||||
これは<abbr title="未満"><code>lt</code></abbr>も同じです。
|
||||
これは<abbr title="less than – より小さい"><code>lt</code></abbr>も同じです。
|
||||
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial006.py hl[11] *}
|
||||
{* ../../docs_src/path_params_numeric_validations/tutorial006_an_py39.py hl[13] *}
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
`Query`と`Path`(そしてまだ見たことない他のもの)では、[クエリパラメータと文字列の検証](query-params-str-validations.md){.internal-link target=_blank}と同じようにメタデータと文字列の検証を宣言することができます。
|
||||
|
||||
また、数値のバリデーションを宣言することもできます:
|
||||
|
||||
* `gt`: より大きい(`g`reater `t`han)
|
||||
* `ge`: 以上(`g`reater than or `e`qual)
|
||||
* `lt`: より小さい(`l`ess `t`han)
|
||||
* `le`: 以下(`l`ess than or `e`qual)
|
||||
* `gt`: `g`reater `t`han
|
||||
* `ge`: `g`reater than or `e`qual
|
||||
* `lt`: `l`ess `t`han
|
||||
* `le`: `l`ess than or `e`qual
|
||||
|
||||
/// info | 情報
|
||||
|
||||
`Query`、`Path`などは後に共通の`Param`クラスのサブクラスを見ることになります。(使う必要はありません)
|
||||
`Query`、`Path`、および後で見る他のクラスは、共通の`Param`クラスのサブクラスです。
|
||||
|
||||
そして、それらすべては、これまで見てきた追加のバリデーションとメタデータと同じパラメータを共有しています。
|
||||
それらはすべて、これまで見てきた追加のバリデーションとメタデータの同じパラメータを共有しています。
|
||||
|
||||
///
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# パスパラメータ
|
||||
# パスパラメータ { #path-parameters }
|
||||
|
||||
Pythonのformat文字列と同様のシンタックスで「パスパラメータ」や「パス変数」を宣言できます:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial001.py hl[6,7] *}
|
||||
{* ../../docs_src/path_params/tutorial001_py39.py hl[6:7] *}
|
||||
|
||||
パスパラメータ `item_id` の値は、引数 `item_id` として関数に渡されます。
|
||||
|
||||
しがたって、この例を実行して <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a> にアクセスすると、次のレスポンスが表示されます。
|
||||
したがって、この例を実行して <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a> にアクセスすると、次のレスポンスが表示されます。
|
||||
|
||||
```JSON
|
||||
{"item_id":"foo"}
|
||||
```
|
||||
|
||||
## パスパラメータと型
|
||||
## 型付きパスパラメータ { #path-parameters-with-types }
|
||||
|
||||
標準のPythonの型アノテーションを使用して、関数内のパスパラメータの型を宣言できます:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial002.py hl[7] *}
|
||||
{* ../../docs_src/path_params/tutorial002_py39.py hl[7] *}
|
||||
|
||||
ここでは、 `item_id` は `int` として宣言されています。
|
||||
|
||||
@@ -26,7 +26,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
|
||||
|
||||
///
|
||||
|
||||
## データ<abbr title="別名: serialization, parsing, marshalling">変換</abbr>
|
||||
## データ<abbr title="別名: serialization, parsing, marshalling">変換</abbr> { #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,68 +38,69 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
|
||||
|
||||
関数が受け取った(および返した)値は、文字列の `"3"` ではなく、Pythonの `int` としての `3` であることに注意してください。
|
||||
|
||||
したがって、型宣言を使用すると、**FastAPI**は自動リクエスト <abbr title="HTTPリクエストで受け取った文字列をPythonデータへ変換する">"解析"</abbr> を行います。
|
||||
したがって、その型宣言を使うと、**FastAPI**は自動リクエスト <abbr title="HTTPリクエストで受け取った文字列をPythonデータへ変換する">"解析"</abbr> を行います。
|
||||
|
||||
///
|
||||
|
||||
## データバリデーション
|
||||
## データバリデーション { #data-validation }
|
||||
|
||||
しかしブラウザで <a href="http://127.0.0.1:8000/items/foo" class="external-link" target="_blank">http://127.0.0.1:8000/items/foo</a> を開くと、次のHTTPエラーが表示されます:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": [
|
||||
"path",
|
||||
"item_id"
|
||||
],
|
||||
"msg": "value is not a valid integer",
|
||||
"type": "type_error.integer"
|
||||
}
|
||||
]
|
||||
"detail": [
|
||||
{
|
||||
"type": "int_parsing",
|
||||
"loc": [
|
||||
"path",
|
||||
"item_id"
|
||||
],
|
||||
"msg": "Input should be a valid integer, unable to parse string as an integer",
|
||||
"input": "foo"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
これは、パスパラメータ `item_id` が `int` ではない値 `"foo"` だからです。
|
||||
|
||||
<a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a> で見られるように、intのかわりに `float` が与えられた場合にも同様なエラーが表示されます。
|
||||
<a href="http://127.0.0.1:8000/items/4.2" class="external-link" target="_blank">http://127.0.0.1:8000/items/4.2</a> で見られるように、`int` のかわりに `float` が与えられた場合にも同様なエラーが表示されます。
|
||||
|
||||
/// check | 確認
|
||||
|
||||
したがって、Pythonの型宣言を使用することで、**FastAPI**はデータのバリデーションを行います。
|
||||
したがって、同じPythonの型宣言を使用することで、**FastAPI**はデータのバリデーションを行います。
|
||||
|
||||
表示されたエラーには問題のある箇所が明確に指摘されていることに注意してください。
|
||||
表示されたエラーには、バリデーションが通らなかった箇所が明確に示されていることに注意してください。
|
||||
|
||||
これは、APIに関連するコードの開発およびデバッグに非常に役立ちます。
|
||||
これは、APIとやり取りするコードを開発・デバッグする際に非常に役立ちます。
|
||||
|
||||
///
|
||||
|
||||
## ドキュメント
|
||||
## ドキュメント { #documentation }
|
||||
|
||||
そしてブラウザで <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> を開くと、以下の様な自動的に生成された対話的なドキュメントが表示されます。
|
||||
そしてブラウザで <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a> を開くと、以下の様な自動的に生成された対話的なAPIドキュメントが表示されます。
|
||||
|
||||
<img src="/img/tutorial/path-params/image01.png">
|
||||
|
||||
/// check | 確認
|
||||
|
||||
繰り返しになりますが、Python型宣言を使用するだけで、**FastAPI**は対話的なAPIドキュメントを自動的に生成します(Swagger UIを統合)。
|
||||
繰り返しになりますが、同じPython型宣言を使用するだけで、**FastAPI**は対話的なドキュメントを自動的に生成します(Swagger UIを統合)。
|
||||
|
||||
パスパラメータが整数として宣言されていることに注意してください。
|
||||
|
||||
///
|
||||
|
||||
## 標準であることのメリット、ドキュメンテーションの代替物
|
||||
## 標準ベースのメリット、ドキュメンテーションの代替物 { #standards-based-benefits-alternative-documentation }
|
||||
|
||||
また、生成されたスキーマが <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" class="external-link" target="_blank">OpenAPI</a> 標準に従っているので、互換性のあるツールが多数あります。
|
||||
また、生成されたスキーマが <a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md" class="external-link" target="_blank">OpenAPI</a> 標準に従っているので、互換性のあるツールが多数あります。
|
||||
|
||||
このため、**FastAPI**自体が代替のAPIドキュメントを提供します(ReDocを使用)。これは、 <a href="http://127.0.0.1:8000/redoc" class="external-link" target="_blank">http://127.0.0.1:8000/redoc</a> にアクセスすると確認できます。
|
||||
|
||||
<img src="/img/tutorial/path-params/image02.png">
|
||||
|
||||
同様に、互換性のあるツールが多数あります(多くの言語用のコード生成ツールを含む)。
|
||||
同様に、互換性のあるツールが多数あります。多くの言語用のコード生成ツールを含みます。
|
||||
|
||||
## Pydantic
|
||||
## Pydantic { #pydantic }
|
||||
|
||||
すべてのデータバリデーションは <a href="https://docs.pydantic.dev/" class="external-link" target="_blank">Pydantic</a> によって内部で実行されるため、Pydanticの全てのメリットが得られます。そして、安心して利用することができます。
|
||||
|
||||
@@ -107,7 +108,7 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
|
||||
|
||||
これらのいくつかについては、チュートリアルの次の章で説明します。
|
||||
|
||||
## 順序の問題
|
||||
## 順序の問題 { #order-matters }
|
||||
|
||||
*path operations* を作成する際、固定パスをもつ状況があり得ます。
|
||||
|
||||
@@ -117,29 +118,29 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
|
||||
|
||||
*path operations* は順に評価されるので、 `/users/me` が `/users/{user_id}` よりも先に宣言されているか確認する必要があります:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial003.py hl[6,11] *}
|
||||
{* ../../docs_src/path_params/tutorial003_py39.py hl[6,11] *}
|
||||
|
||||
それ以外の場合、 `/users/{users_id}` は `/users/me` としてもマッチします。値が「"me"」であるパラメータ `user_id` を受け取ると「考え」ます。
|
||||
それ以外の場合、 `/users/{user_id}` は `/users/me` としてもマッチします。値が `"me"` であるパラメータ `user_id` を受け取ると「考え」ます。
|
||||
|
||||
## 定義済みの値
|
||||
同様に、path operation を再定義することはできません:
|
||||
|
||||
*パスパラメータ*を受け取る *path operation* をもち、有効な*パスパラメータ*の値を事前に定義したい場合は、標準のPython <abbr title="Enumeration">`Enum`</abbr> を利用できます。
|
||||
{* ../../docs_src/path_params/tutorial003b_py39.py hl[6,11] *}
|
||||
|
||||
### `Enum` クラスの作成
|
||||
パスは最初にマッチしたものが常に使われるため、最初のものが常に使用されます。
|
||||
|
||||
## 定義済みの値 { #predefined-values }
|
||||
|
||||
*パスパラメータ*を受け取る *path operation* をもち、有効な*パスパラメータ*の値を事前に定義したい場合は、標準のPython <abbr title="Enumeration - 列挙型">`Enum`</abbr> を利用できます。
|
||||
|
||||
### `Enum` クラスの作成 { #create-an-enum-class }
|
||||
|
||||
`Enum` をインポートし、 `str` と `Enum` を継承したサブクラスを作成します。
|
||||
|
||||
`str` を継承することで、APIドキュメントは値が `文字列` でなければいけないことを知り、正確にレンダリングできるようになります。
|
||||
`str` を継承することで、APIドキュメントは値が `string` 型でなければいけないことを知り、正確にレンダリングできるようになります。
|
||||
|
||||
そして、固定値のクラス属性を作ります。すると、その値が使用可能な値となります:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005.py hl[1,6,7,8,9] *}
|
||||
|
||||
/// info | 情報
|
||||
|
||||
<a href="https://docs.python.org/3/library/enum.html" class="external-link" target="_blank">Enumerations (もしくは、enums)はPython 3.4以降で利用できます</a>。
|
||||
|
||||
///
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[1,6:9] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
@@ -147,33 +148,33 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
|
||||
|
||||
///
|
||||
|
||||
### *パスパラメータ*の宣言
|
||||
### *パスパラメータ*の宣言 { #declare-a-path-parameter }
|
||||
|
||||
次に、作成したenumクラスである`ModelName`を使用した型アノテーションをもつ*パスパラメータ*を作成します:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005.py hl[16] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[16] *}
|
||||
|
||||
### ドキュメントの確認
|
||||
### ドキュメントの確認 { #check-the-docs }
|
||||
|
||||
*パスパラメータ*の利用可能な値が事前に定義されているので、対話的なドキュメントで適切に表示できます:
|
||||
|
||||
<img src="/img/tutorial/path-params/image03.png">
|
||||
|
||||
### Python*列挙型*の利用
|
||||
### Python*列挙型*の利用 { #working-with-python-enumerations }
|
||||
|
||||
*パスパラメータ*の値は*列挙型メンバ*となります。
|
||||
|
||||
#### *列挙型メンバ*の比較
|
||||
#### *列挙型メンバ*の比較 { #compare-enumeration-members }
|
||||
|
||||
これは、作成した列挙型 `ModelName` の*列挙型メンバ*と比較できます:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005.py hl[17] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[17] *}
|
||||
|
||||
#### *列挙値*の取得
|
||||
#### *列挙値*の取得 { #get-the-enumeration-value }
|
||||
|
||||
`model_name.value` 、もしくは一般に、 `your_enum_member.value` を使用して実際の値 (この場合は `str`) を取得できます。
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005.py hl[20] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[20] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
@@ -181,13 +182,13 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
|
||||
|
||||
///
|
||||
|
||||
#### *列挙型メンバ*の返却
|
||||
#### *列挙型メンバ*の返却 { #return-enumeration-members }
|
||||
|
||||
*path operation* から*列挙型メンバ*を返すことができます。JSONボディ(`dict` など)でネストすることもできます。
|
||||
*path operation* から*列挙型メンバ*を返すことができます。JSONボディ(例: `dict`)でネストすることもできます。
|
||||
|
||||
それらはクライアントに返される前に適切な値 (この場合は文字列) に変換されます。
|
||||
|
||||
{* ../../docs_src/path_params/tutorial005.py hl[18,21,23] *}
|
||||
{* ../../docs_src/path_params/tutorial005_py39.py hl[18,21,23] *}
|
||||
|
||||
クライアントは以下の様なJSONレスポンスを得ます:
|
||||
|
||||
@@ -198,23 +199,23 @@ Pythonのformat文字列と同様のシンタックスで「パスパラメー
|
||||
}
|
||||
```
|
||||
|
||||
## パスを含んだパスパラメータ
|
||||
## パスを含んだパスパラメータ { #path-parameters-containing-paths }
|
||||
|
||||
パス `/files/{file_path}` となる *path operation* を持っているとしましょう。
|
||||
|
||||
ただし、 `home/johndoe/myfile.txt` のような*パス*を含んだ `file_path` が必要です。
|
||||
|
||||
したがって、URLは `/files/home/johndoe/myfile.txt` の様になります。
|
||||
したがって、そのファイルのURLは `/files/home/johndoe/myfile.txt` の様になります。
|
||||
|
||||
### OpenAPIサポート
|
||||
### OpenAPIサポート { #openapi-support }
|
||||
|
||||
OpenAPIはテストや定義が困難なシナリオにつながる可能性があるため、内部に*パス*を含む*パスパラメータ*の宣言をサポートしていません。
|
||||
|
||||
それにも関わらず、Starletteの内部ツールのひとつを使用することで、**FastAPI**はそれが実現できます。
|
||||
|
||||
そして、パラメータがパスを含むべきであることを明示的にドキュメントに追加することなく、機能します。
|
||||
そして、パラメータがパスを含むべきであることを示すドキュメントを追加しなくても、ドキュメントは動作します。
|
||||
|
||||
### パス変換
|
||||
### パスコンバーター { #path-convertor }
|
||||
|
||||
Starletteのオプションを直接使用することで、以下のURLの様な*パス*を含んだ、*パスパラメータ*の宣言ができます:
|
||||
|
||||
@@ -226,17 +227,17 @@ Starletteのオプションを直接使用することで、以下のURLの様
|
||||
|
||||
したがって、以下の様に使用できます:
|
||||
|
||||
{* ../../docs_src/path_params/tutorial004.py hl[6] *}
|
||||
{* ../../docs_src/path_params/tutorial004_py39.py hl[6] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
最初のスラッシュ (`/`)が付いている `/home/johndoe/myfile.txt` をパラメータが含んでいる必要があります。
|
||||
最初のスラッシュ (`/`)が付いている `/home/johndoe/myfile.txt` をパラメータが含んでいる必要があるかもしれません。
|
||||
|
||||
この場合、URLは `files` と `home` の間にダブルスラッシュ (`//`) のある、 `/files//home/johndoe/myfile.txt` になります。
|
||||
|
||||
///
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
簡潔で、本質的で、標準的なPythonの型宣言を使用することで、**FastAPI**は以下を行います:
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# クエリパラメータモデル
|
||||
# クエリパラメータモデル { #query-parameter-models }
|
||||
|
||||
もし関連する**複数のクエリパラメータ**から成るグループがあるなら、それらを宣言するために、**Pydanticモデル**を作成できます。
|
||||
|
||||
こうすることで、**複数の場所**で**そのPydanticモデルを再利用**でき、バリデーションやメタデータを、すべてのクエリパラメータに対して一度に宣言できます。😎
|
||||
こうすることで、**複数の場所**で**そのモデルを再利用**でき、バリデーションやメタデータを、すべてのパラメータに対して一度に宣言できます。😎
|
||||
|
||||
/// note | 備考
|
||||
|
||||
@@ -10,15 +10,15 @@
|
||||
|
||||
///
|
||||
|
||||
## クエリパラメータにPydanticモデルを使用する
|
||||
## Pydanticモデルを使ったクエリパラメータ { #query-parameters-with-a-pydantic-model }
|
||||
|
||||
必要な**複数のクエリパラメータ**を**Pydanticモデル**で宣言し、さらに、それを `Query` として宣言しましょう:
|
||||
必要な**クエリパラメータ**を**Pydanticモデル**で宣言し、さらに、そのパラメータを `Query` として宣言しましょう:
|
||||
|
||||
{* ../../docs_src/query_param_models/tutorial001_an_py310.py hl[9:13,17] *}
|
||||
|
||||
**FastAPI**は、リクエストの**クエリパラメータ**からそれぞれの**フィールド**のデータを**抽出**し、定義された**Pydanticモデル**を提供します。
|
||||
**FastAPI**は、リクエストの**クエリパラメータ**からそれぞれの**フィールド**のデータを**抽出**し、定義したPydanticモデルを提供します。
|
||||
|
||||
## ドキュメントの確認
|
||||
## ドキュメントの確認 { #check-the-docs }
|
||||
|
||||
対話的APIドキュメント `/docs` でクエリパラメータを確認できます:
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
<img src="/img/tutorial/query-param-models/image01.png">
|
||||
</div>
|
||||
|
||||
## 余分なクエリパラメータを禁止する
|
||||
## 余分なクエリパラメータを禁止する { #forbid-extra-query-parameters }
|
||||
|
||||
特定の(あまり一般的ではないかもしれない)ケースで、受け付けるクエリパラメータを**制限**する必要があるかもしれません。
|
||||
特定の(あまり一般的ではないかもしれない)ユースケースで、受け取りたいクエリパラメータを**制限**したい場合があります。
|
||||
|
||||
Pydanticのモデルの Configuration を利用して、 `extra` フィールドを `forbid` とすることができます。
|
||||
Pydanticのモデル設定を使って、あらゆる `extra` フィールドを `forbid` にできます。
|
||||
|
||||
{* ../../docs_src/query_param_models/tutorial002_an_py310.py hl[10] *}
|
||||
|
||||
@@ -42,7 +42,7 @@ Pydanticのモデルの Configuration を利用して、 `extra` フィールド
|
||||
https://example.com/items/?limit=10&tool=plumbus
|
||||
```
|
||||
|
||||
クエリパラメータ `tool` が許可されていないことを通知する**エラー**レスポンスが返されます。
|
||||
クエリパラメータ `tool` が許可されていないことを伝える**エラー**レスポンスが返されます。
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -57,7 +57,7 @@ https://example.com/items/?limit=10&tool=plumbus
|
||||
}
|
||||
```
|
||||
|
||||
## まとめ
|
||||
## まとめ { #summary }
|
||||
|
||||
**FastAPI**では、**クエリパラメータ**を宣言するために、**Pydanticモデル**を使用できます。😎
|
||||
|
||||
|
||||
@@ -1,120 +1,228 @@
|
||||
# クエリパラメータと文字列の検証
|
||||
# クエリパラメータと文字列の検証 { #query-parameters-and-string-validations }
|
||||
|
||||
**FastAPI** ではパラメータの追加情報とバリデーションを宣言することができます。
|
||||
|
||||
以下のアプリケーションを例にしてみましょう:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial001.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *}
|
||||
|
||||
クエリパラメータ `q` は `Optional[str]` 型で、`None` を許容する `str` 型を意味しており、デフォルトは `None` です。そのため、FastAPIはそれが必須ではないと理解します。
|
||||
クエリパラメータ `q` は `str | None` 型で、`str` 型ですが `None` にもなり得ることを意味し、実際にデフォルト値は `None` なので、FastAPIはそれが必須ではないと理解します。
|
||||
|
||||
/// note | 備考
|
||||
|
||||
FastAPIは、 `q` はデフォルト値が `=None` であるため、必須ではないと理解します。
|
||||
FastAPIは、 `q` はデフォルト値が `= None` であるため、必須ではないと理解します。
|
||||
|
||||
`Optional[str]` における `Optional` はFastAPIには利用されませんが、エディターによるより良いサポートとエラー検出を可能にします。
|
||||
`str | None` を使うことで、エディターによるより良いサポートとエラー検出を可能にします。
|
||||
|
||||
///
|
||||
|
||||
## バリデーションの追加
|
||||
## バリデーションの追加 { #additional-validation }
|
||||
|
||||
`q`はオプショナルですが、もし値が渡されてきた場合には、**50文字を超えないこと**を強制してみましょう。
|
||||
`q`はオプショナルですが、もし値が渡されてきた場合には、**長さが50文字を超えないこと**を強制してみましょう。
|
||||
|
||||
### `Query`のインポート
|
||||
### `Query` と `Annotated` のインポート { #import-query-and-annotated }
|
||||
|
||||
そのために、まずは`fastapi`から`Query`をインポートします:
|
||||
そのために、まずは以下をインポートします:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial002.py hl[3] *}
|
||||
* `fastapi` から `Query`
|
||||
* `typing` から `Annotated`
|
||||
|
||||
## デフォルト値として`Query`を使用
|
||||
{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *}
|
||||
|
||||
パラメータのデフォルト値として使用し、パラメータ`max_length`を50に設定します:
|
||||
/// info | 情報
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial002.py hl[9] *}
|
||||
FastAPI はバージョン 0.95.0 で `Annotated` のサポートを追加し(推奨し始め)ました。
|
||||
|
||||
デフォルト値`None`を`Query(default=None)`に置き換える必要があるので、`Query`の最初の引数はデフォルト値を定義するのと同じです。
|
||||
古いバージョンの場合、`Annotated` を使おうとするとエラーになります。
|
||||
|
||||
`Annotated` を使う前に、FastAPI のバージョンを少なくとも 0.95.1 にするために、[FastAPI のバージョンをアップグレード](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}してください。
|
||||
|
||||
///
|
||||
|
||||
## `q` パラメータの型で `Annotated` を使う { #use-annotated-in-the-type-for-the-q-parameter }
|
||||
|
||||
以前、[Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.internal-link target=_blank} で `Annotated` を使ってパラメータにメタデータを追加できると説明したことを覚えていますか?
|
||||
|
||||
いよいよ FastAPI で使うときです。 🚀
|
||||
|
||||
次の型アノテーションがありました:
|
||||
|
||||
//// 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` です。
|
||||
|
||||
では、面白いところに進みましょう。 🎉
|
||||
|
||||
## `q` パラメータの `Annotated` に `Query` を追加する { #add-query-to-annotated-in-the-q-parameter }
|
||||
|
||||
追加情報(この場合は追加のバリデーション)を入れられる `Annotated` ができたので、`Annotated` の中に `Query` を追加し、パラメータ `max_length` を `50` に設定します:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *}
|
||||
|
||||
デフォルト値は引き続き `None` なので、このパラメータは依然としてオプショナルです。
|
||||
|
||||
しかし、`Annotated` の中に `Query(max_length=50)` を入れることで、この値に **追加のバリデーション** をしたい、最大 50 文字にしたい、と FastAPI に伝えています。 😎
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
ここでは **クエリパラメータ** なので `Query()` を使っています。後で `Path()`、`Body()`、`Header()`、`Cookie()` など、`Query()` と同じ引数を受け取れるものも見ていきます。
|
||||
|
||||
///
|
||||
|
||||
FastAPI は次を行います:
|
||||
|
||||
* 最大長が 50 文字であることを確かめるようデータを **検証** する
|
||||
* データが有効でないときに、クライアントに **明確なエラー** を表示する
|
||||
* OpenAPI スキーマの *path operation* にパラメータを **ドキュメント化** する(その結果、**自動ドキュメント UI** に表示されます)
|
||||
|
||||
## 代替(古い方法): デフォルト値としての `Query` { #alternative-old-query-as-the-default-value }
|
||||
|
||||
FastAPI の以前のバージョン(<abbr title="before 2023-03">0.95.0</abbr> より前)では、パラメータのデフォルト値として `Query` を使う必要があり、`Annotated` の中に入れるのではありませんでした。これを使ったコードを見かける可能性が高いので、説明します。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
新しいコードでは、可能な限り上で説明したとおり `Annotated` を使ってください。複数の利点(後述)があり、欠点はありません。 🍰
|
||||
|
||||
///
|
||||
|
||||
関数パラメータのデフォルト値として `Query()` を使い、パラメータ `max_length` を 50 に設定する方法は次のとおりです:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *}
|
||||
|
||||
この場合(`Annotated` を使わない場合)、関数内のデフォルト値 `None` を `Query()` に置き換える必要があるため、`Query(default=None)` のパラメータでデフォルト値を設定する必要があります。これは(少なくとも FastAPI にとっては)そのデフォルト値を定義するのと同じ目的を果たします。
|
||||
|
||||
なので:
|
||||
|
||||
```Python
|
||||
q: Optional[str] = Query(default=None)
|
||||
q: str | None = Query(default=None)
|
||||
```
|
||||
|
||||
...を以下と同じようにパラメータをオプションにします:
|
||||
...はデフォルト値 `None` を持つオプショナルなパラメータになり、以下と同じです:
|
||||
|
||||
|
||||
```Python
|
||||
q: Optional[str] = None
|
||||
q: str | None = None
|
||||
```
|
||||
|
||||
しかし、これはクエリパラメータとして明示的に宣言しています。
|
||||
|
||||
/// info | 情報
|
||||
|
||||
FastAPIは以下の部分を気にすることを覚えておいてください:
|
||||
|
||||
```Python
|
||||
= None
|
||||
```
|
||||
|
||||
もしくは:
|
||||
|
||||
```Python
|
||||
= Query(default=None)
|
||||
```
|
||||
|
||||
そして、 `None` を利用することでクエリパラメータが必須ではないと検知します。
|
||||
|
||||
`Optional` の部分は、エディターによるより良いサポートを可能にします。
|
||||
|
||||
///
|
||||
ただし `Query` のバージョンでは、クエリパラメータであることを明示的に宣言しています。
|
||||
|
||||
そして、さらに多くのパラメータを`Query`に渡すことができます。この場合、文字列に適用される、`max_length`パラメータを指定します。
|
||||
|
||||
```Python
|
||||
q: Union[str, None] = Query(default=None, max_length=50)
|
||||
q: str | None = Query(default=None, max_length=50)
|
||||
```
|
||||
|
||||
これにより、データを検証し、データが有効でない場合は明確なエラーを表示し、OpenAPIスキーマの *path operation* にパラメータを記載します。
|
||||
|
||||
## バリデーションをさらに追加する
|
||||
### デフォルト値としての `Query` または `Annotated` 内の `Query` { #query-as-the-default-value-or-in-annotated }
|
||||
|
||||
`Annotated` の中で `Query` を使う場合、`Query` の `default` パラメータは使えないことに注意してください。
|
||||
|
||||
その代わりに、関数パラメータの実際のデフォルト値を使います。そうしないと整合性が取れなくなります。
|
||||
|
||||
例えば、これは許可されません:
|
||||
|
||||
```Python
|
||||
q: Annotated[str, Query(default="rick")] = "morty"
|
||||
```
|
||||
|
||||
...なぜなら、デフォルト値が `"rick"` なのか `"morty"` なのかが不明確だからです。
|
||||
|
||||
そのため、(できれば)次のようにします:
|
||||
|
||||
```Python
|
||||
q: Annotated[str, Query()] = "rick"
|
||||
```
|
||||
|
||||
...または、古いコードベースでは次のようなものが見つかるでしょう:
|
||||
|
||||
```Python
|
||||
q: str = Query(default="rick")
|
||||
```
|
||||
|
||||
### `Annotated` の利点 { #advantages-of-annotated }
|
||||
|
||||
関数パラメータのデフォルト値スタイルではなく、**`Annotated` を使うことが推奨** されます。複数の理由で **より良い** からです。 🤓
|
||||
|
||||
**関数パラメータ** の **デフォルト値** は **実際のデフォルト値** であり、Python 全般としてより直感的です。 😌
|
||||
|
||||
FastAPI なしで同じ関数を **別の場所** から **呼び出しても**、**期待どおりに動作** します。**必須** パラメータ(デフォルト値がない)があれば、**エディター** がエラーで知らせてくれますし、**Python** も必須パラメータを渡さずに実行すると文句を言います。
|
||||
|
||||
`Annotated` を使わずに **(古い)デフォルト値スタイル** を使う場合、FastAPI なしでその関数を **別の場所** で呼び出すとき、正しく動かすために関数へ引数を渡すことを **覚えておく** 必要があります。そうしないと値が期待と異なります(例えば `str` の代わりに `QueryInfo` か、それに類するものになります)。また、エディターも警告せず、Python もその関数の実行で文句を言いません。内部の処理がエラーになるときに初めて問題が出ます。
|
||||
|
||||
`Annotated` は複数のメタデータアノテーションを持てるので、<a href="https://typer.tiangolo.com/" class="external-link" target="_blank">Typer</a> のような別ツールと同じ関数を使うこともできます。 🚀
|
||||
|
||||
## バリデーションをさらに追加する { #add-more-validations }
|
||||
|
||||
パラメータ`min_length`も追加することができます:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial003.py hl[10] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *}
|
||||
|
||||
## 正規表現の追加
|
||||
## 正規表現の追加 { #add-regular-expressions }
|
||||
|
||||
パラメータが一致するべき<abbr title="正規表現とは、文字列の検索パターンを定義する文字列です。">正規表現</abbr>を定義することができます:
|
||||
パラメータが一致するべき <abbr title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings.">正規表現</abbr> `pattern` を定義することができます:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial004.py hl[11] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
|
||||
|
||||
この特定の正規表現は受け取ったパラメータの値をチェックします:
|
||||
この特定の正規表現パターンは受け取ったパラメータの値をチェックします:
|
||||
|
||||
* `^`: は、これ以降の文字で始まり、これより以前には文字はありません。
|
||||
* `fixedquery`: は、正確な`fixedquery`を持っています.
|
||||
* `$`: で終わる場合、`fixedquery`以降には文字はありません.
|
||||
|
||||
もしこれらすべての **正規表現**のアイデアについて迷っていても、心配しないでください。多くの人にとって難しい話題です。正規表現を必要としなくても、まだ、多くのことができます。
|
||||
もしこれらすべての **「正規表現」** のアイデアについて迷っていても、心配しないでください。多くの人にとって難しい話題です。正規表現を必要としなくても、まだ、多くのことができます。
|
||||
|
||||
しかし、あなたがそれらを必要とし、学ぶときにはすでに、 **FastAPI**で直接それらを使用することができます。
|
||||
これで、必要になったときにはいつでも **FastAPI** で使えることが分かりました。
|
||||
|
||||
## デフォルト値
|
||||
## デフォルト値 { #default-values }
|
||||
|
||||
第一引数に`None`を渡して、デフォルト値として使用するのと同じように、他の値を渡すこともできます。
|
||||
もちろん、`None` 以外のデフォルト値も使えます。
|
||||
|
||||
クエリパラメータ`q`の`min_length`を`3`とし、デフォルト値を`fixedquery`としてみましょう:
|
||||
クエリパラメータ `q` の `min_length` を `3` とし、デフォルト値を `"fixedquery"` として宣言したいとします:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial005.py hl[7] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}
|
||||
|
||||
/// note | 備考
|
||||
|
||||
デフォルト値を指定すると、パラメータは任意になります。
|
||||
`None` を含む任意の型のデフォルト値があると、パラメータはオプショナル(必須ではない)になります。
|
||||
|
||||
///
|
||||
|
||||
## 必須にする
|
||||
## 必須パラメータ { #required-parameters }
|
||||
|
||||
これ以上、バリデーションやメタデータを宣言する必要のない場合は、デフォルト値を指定しないだけでクエリパラメータ`q`を必須にすることができます。以下のように:
|
||||
これ以上、バリデーションやメタデータを宣言する必要がない場合は、デフォルト値を宣言しないだけでクエリパラメータ `q` を必須にできます。以下のように:
|
||||
|
||||
```Python
|
||||
q: str
|
||||
@@ -123,42 +231,42 @@ q: str
|
||||
以下の代わりに:
|
||||
|
||||
```Python
|
||||
q: Union[str, None] = None
|
||||
q: str | None = None
|
||||
```
|
||||
|
||||
現在は以下の例のように`Query`で宣言しています:
|
||||
しかし今は、例えば次のように `Query` で宣言しています:
|
||||
|
||||
```Python
|
||||
q: Union[str, None] = Query(default=None, min_length=3)
|
||||
q: Annotated[str | None, Query(min_length=3)] = None
|
||||
```
|
||||
|
||||
そのため、`Query`を使用して必須の値を宣言する必要がある場合は、第一引数に`...`を使用することができます:
|
||||
そのため、`Query` を使いながら値を必須として宣言したい場合は、単にデフォルト値を宣言しません:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial006.py hl[7] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
|
||||
|
||||
/// info | 情報
|
||||
### 必須、`None` にできる { #required-can-be-none }
|
||||
|
||||
これまで`...`を見たことがない方へ: これは特殊な単一値です。<a href="https://docs.python.org/3/library/constants.html#Ellipsis" class="external-link" target="_blank">Pythonの一部であり、"Ellipsis"と呼ばれています</a>。
|
||||
パラメータが `None` を受け付けるが、それでも必須である、と宣言できます。これにより、値が `None` であってもクライアントは値を送らなければならなくなります。
|
||||
|
||||
///
|
||||
そのために、`None` が有効な型であることを宣言しつつ、単にデフォルト値を宣言しません:
|
||||
|
||||
これは **FastAPI** にこのパラメータが必須であることを知らせます。
|
||||
{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *}
|
||||
|
||||
## クエリパラメータのリスト / 複数の値
|
||||
## クエリパラメータのリスト / 複数の値 { #query-parameter-list-multiple-values }
|
||||
|
||||
クエリパラメータを明示的に`Query`で宣言した場合、値のリストを受け取るように宣言したり、複数の値を受け取るように宣言したりすることもできます。
|
||||
クエリパラメータを明示的に `Query` で定義すると、値のリストを受け取るように宣言したり、言い換えると複数の値を受け取るように宣言したりすることもできます。
|
||||
|
||||
例えば、URL内に複数回出現するクエリパラメータ`q`を宣言するには以下のように書きます:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial011.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *}
|
||||
|
||||
そしてURLは以下です:
|
||||
そして、次のような URL なら:
|
||||
|
||||
```
|
||||
http://localhost:8000/items/?q=foo&q=bar
|
||||
```
|
||||
|
||||
複数の*クエリパラメータ*の値`q`(`foo`と`bar`)を*path operation関数*内で*関数パラメータ*`q`としてPythonの`list`を受け取ることになります。
|
||||
*path operation function* 内の *function parameter* `q` で、複数の `q` *query parameters'* 値(`foo` と `bar`)を Python の `list` として受け取ります。
|
||||
|
||||
そのため、このURLのレスポンスは以下のようになります:
|
||||
|
||||
@@ -179,15 +287,15 @@ http://localhost:8000/items/?q=foo&q=bar
|
||||
|
||||
対話的APIドキュメントは複数の値を許可するために自動的に更新されます。
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/query-params-str-validations/image02.png">
|
||||
<img src="/img/tutorial/query-params-str-validations/image02.png">
|
||||
|
||||
### デフォルト値を持つ、クエリパラメータのリスト / 複数の値
|
||||
### デフォルト値を持つ、クエリパラメータのリスト / 複数の値 { #query-parameter-list-multiple-values-with-defaults }
|
||||
|
||||
また、値が指定されていない場合はデフォルトの`list`を定義することもできます。
|
||||
また、値が指定されていない場合はデフォルトの `list` を定義することもできます。
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial012.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
|
||||
|
||||
以下のURLを開くと:
|
||||
以下にアクセスすると:
|
||||
|
||||
```
|
||||
http://localhost:8000/items/
|
||||
@@ -204,21 +312,21 @@ http://localhost:8000/items/
|
||||
}
|
||||
```
|
||||
|
||||
#### `list`を使う
|
||||
#### `list` だけを使う { #using-just-list }
|
||||
|
||||
`List[str]`の代わりに直接`list`を使うこともできます:
|
||||
`list[str]` の代わりに直接 `list` を使うこともできます:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial013.py hl[7] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
|
||||
|
||||
/// note | 備考
|
||||
|
||||
この場合、FastAPIはリストの内容をチェックしないことを覚えておいてください。
|
||||
|
||||
例えば`List[int]`はリストの内容が整数であるかどうかをチェックします(そして、文書化します)。しかし`list`だけではそうしません。
|
||||
例えば`list[int]`はリストの内容が整数であるかどうかをチェックします(そして、文書化します)。しかし`list`だけではそうしません。
|
||||
|
||||
///
|
||||
|
||||
## より多くのメタデータを宣言する
|
||||
## より多くのメタデータを宣言する { #declare-more-metadata }
|
||||
|
||||
パラメータに関する情報をさらに追加することができます。
|
||||
|
||||
@@ -234,13 +342,13 @@ http://localhost:8000/items/
|
||||
|
||||
`title`を追加できます:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial007.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *}
|
||||
|
||||
`description`を追加できます:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial008.py hl[13] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *}
|
||||
|
||||
## エイリアスパラメータ
|
||||
## エイリアスパラメータ { #alias-parameters }
|
||||
|
||||
パラメータに`item-query`を指定するとします.
|
||||
|
||||
@@ -258,23 +366,91 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
|
||||
|
||||
それならば、`alias`を宣言することができます。エイリアスはパラメータの値を見つけるのに使用されます:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial009.py hl[9] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *}
|
||||
|
||||
## 非推奨パラメータ
|
||||
## パラメータを非推奨にする { #deprecating-parameters }
|
||||
|
||||
さて、このパラメータが気に入らなくなったとしましょう
|
||||
さて、このパラメータが気に入らなくなったとしましょう。
|
||||
|
||||
それを使っているクライアントがいるので、しばらくは残しておく必要がありますが、ドキュメントには<abbr title="使わない方がよい">非推奨</abbr>と明記しておきたいです。
|
||||
それを使っているクライアントがいるので、しばらくは残しておく必要がありますが、ドキュメントには<abbr title="obsolete, recommended not to use it">deprecated</abbr>と明記しておきたいです。
|
||||
|
||||
その場合、`Query`にパラメータ`deprecated=True`を渡します:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial010.py hl[18] *}
|
||||
{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *}
|
||||
|
||||
ドキュメントは以下のようになります:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/query-params-str-validations/image01.png">
|
||||
<img src="/img/tutorial/query-params-str-validations/image01.png">
|
||||
|
||||
## まとめ
|
||||
## OpenAPI からパラメータを除外する { #exclude-parameters-from-openapi }
|
||||
|
||||
生成される OpenAPI スキーマ(つまり自動ドキュメントシステム)からクエリパラメータを除外するには、`Query` のパラメータ `include_in_schema` を `False` に設定します:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *}
|
||||
|
||||
## カスタムバリデーション { #custom-validation }
|
||||
|
||||
上で示したパラメータではできない **カスタムバリデーション** が必要になる場合があります。
|
||||
|
||||
その場合、通常のバリデーション(例: 値が `str` であることの検証)の後に適用される **カスタムバリデータ関数** を使えます。
|
||||
|
||||
これを行うには、`Annotated` の中で <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator" class="external-link" target="_blank">Pydantic の `AfterValidator`</a> を使います。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
Pydantic には <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator" class="external-link" target="_blank">`BeforeValidator`</a> などもあります。 🤓
|
||||
|
||||
///
|
||||
|
||||
例えば、このカスタムバリデータは、<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 – IMDB(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] *}
|
||||
|
||||
/// info | 情報
|
||||
|
||||
これは Pydantic バージョン 2 以上で利用できます。 😎
|
||||
|
||||
///
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
データベースや別の API など、何らかの **外部コンポーネント** との通信が必要なタイプのバリデーションを行う必要がある場合は、代わりに **FastAPI Dependencies** を使うべきです。これについては後で学びます。
|
||||
|
||||
これらのカスタムバリデータは、リクエストで提供された **同じデータのみ** でチェックできるもの向けです。
|
||||
|
||||
///
|
||||
|
||||
### そのコードを理解する { #understand-that-code }
|
||||
|
||||
重要なのは、**`Annotated` の中で関数と一緒に `AfterValidator` を使うこと** だけです。この部分は飛ばしても構いません。 🤸
|
||||
|
||||
---
|
||||
|
||||
ただし、この具体的なコード例が気になっていて、まだ興味が続くなら、追加の詳細を示します。
|
||||
|
||||
#### `value.startswith()` を使う文字列 { #string-with-value-startswith }
|
||||
|
||||
気づきましたか?`value.startswith()` を使う文字列はタプルを受け取れ、そのタプル内の各値をチェックします:
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *}
|
||||
|
||||
#### ランダムなアイテム { #a-random-item }
|
||||
|
||||
`data.items()` で、辞書の各アイテムのキーと値を含むタプルを持つ <abbr title="Something we can iterate on with a for loop, like a list, set, etc.">反復可能オブジェクト</abbr> を取得します。
|
||||
|
||||
この反復可能オブジェクトを `list(data.items())` で適切な `list` に変換します。
|
||||
|
||||
そして `random.choice()` でその `list` から **ランダムな値** を取得するので、`(id, name)` のタプルを得ます。これは `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")` のようになります。
|
||||
|
||||
次に、そのタプルの **2つの値を代入** して、変数 `id` と `name` に入れます。
|
||||
|
||||
つまり、ユーザーが item ID を提供しなかった場合でも、ランダムな提案を受け取ります。
|
||||
|
||||
...これを **単一のシンプルな1行** で行っています。 🤯 Python が好きになりませんか? 🐍
|
||||
|
||||
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *}
|
||||
|
||||
## まとめ { #recap }
|
||||
|
||||
パラメータに追加のバリデーションとメタデータを宣言することができます。
|
||||
|
||||
@@ -285,12 +461,14 @@ http://127.0.0.1:8000/items/?item-query=foobaritems
|
||||
* `description`
|
||||
* `deprecated`
|
||||
|
||||
文字列のためのバリデーション:
|
||||
文字列に固有のバリデーション:
|
||||
|
||||
* `min_length`
|
||||
* `max_length`
|
||||
* `regex`
|
||||
* `pattern`
|
||||
|
||||
この例では、`str`の値のバリデーションを宣言する方法を見てきました。
|
||||
`AfterValidator` を使ったカスタムバリデーション。
|
||||
|
||||
この例では、`str` の値のバリデーションを宣言する方法を見てきました。
|
||||
|
||||
数値のような他の型のバリデーションを宣言する方法は次の章を参照してください。
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# クエリパラメータ
|
||||
# クエリパラメータ { #query-parameters }
|
||||
|
||||
パスパラメータではない関数パラメータを宣言すると、それらは自動的に "クエリ" パラメータとして解釈されます。
|
||||
パスパラメータではない関数パラメータを宣言すると、それらは自動的に「クエリ」パラメータとして解釈されます。
|
||||
|
||||
{* ../../docs_src/query_params/tutorial001.py hl[9] *}
|
||||
{* ../../docs_src/query_params/tutorial001_py39.py hl[9] *}
|
||||
|
||||
クエリはURL内で `?` の後に続くキーとバリューの組で、 `&` で区切られています。
|
||||
|
||||
@@ -24,11 +24,11 @@ http://127.0.0.1:8000/items/?skip=0&limit=10
|
||||
パスパラメータに適用される処理と完全に同様な処理がクエリパラメータにも施されます:
|
||||
|
||||
* エディターサポート (明らかに)
|
||||
* データ「<abbr title="HTTPリクエストで受け取った文字列をPythonデータへ変換する">解析</abbr>」
|
||||
* データ <abbr title="converting the string that comes from an HTTP request into Python data">「解析」</abbr>
|
||||
* データバリデーション
|
||||
* 自動ドキュメント生成
|
||||
|
||||
## デフォルト
|
||||
## デフォルト { #defaults }
|
||||
|
||||
クエリパラメータはパスの固定部分ではないので、オプショナルとしたり、デフォルト値をもつことができます。
|
||||
|
||||
@@ -55,13 +55,13 @@ http://127.0.0.1:8000/items/?skip=20
|
||||
関数内のパラメータの値は以下の様になります:
|
||||
|
||||
* `skip=20`: URL内にセットしたため
|
||||
* `limit=10`: デフォルト値
|
||||
* `limit=10`: デフォルト値だったため
|
||||
|
||||
## オプショナルなパラメータ
|
||||
## オプショナルなパラメータ { #optional-parameters }
|
||||
|
||||
同様に、デフォルト値を `None` とすることで、オプショナルなクエリパラメータを宣言できます:
|
||||
|
||||
{* ../../docs_src/query_params/tutorial002.py hl[9] *}
|
||||
{* ../../docs_src/query_params/tutorial002_py310.py hl[7] *}
|
||||
|
||||
この場合、関数パラメータ `q` はオプショナルとなり、デフォルトでは `None` になります。
|
||||
|
||||
@@ -71,11 +71,11 @@ http://127.0.0.1:8000/items/?skip=20
|
||||
|
||||
///
|
||||
|
||||
## クエリパラメータの型変換
|
||||
## クエリパラメータの型変換 { #query-parameter-type-conversion }
|
||||
|
||||
`bool` 型も宣言できます。これは以下の様に変換されます:
|
||||
`bool` 型も宣言でき、変換されます:
|
||||
|
||||
{* ../../docs_src/query_params/tutorial003.py hl[9] *}
|
||||
{* ../../docs_src/query_params/tutorial003_py310.py hl[7] *}
|
||||
|
||||
この場合、以下にアクセスすると:
|
||||
|
||||
@@ -109,27 +109,28 @@ http://127.0.0.1:8000/items/foo?short=yes
|
||||
|
||||
もしくは、他の大文字小文字のバリエーション (アッパーケース、最初の文字だけアッパーケース、など)で、関数は `short` パラメータを `True` な `bool` 値として扱います。それ以外は `False` になります。
|
||||
|
||||
## 複数のパスパラメータとクエリパラメータ
|
||||
|
||||
複数のパスパラメータとクエリパラメータを同時に宣言できます。**FastAPI**は互いを区別できます。
|
||||
## 複数のパスパラメータとクエリパラメータ { #multiple-path-and-query-parameters }
|
||||
|
||||
複数のパスパラメータとクエリパラメータを同時に宣言できます。**FastAPI**はどれがどれかを把握しています。
|
||||
|
||||
そして特定の順序で宣言しなくてもよいです。
|
||||
|
||||
名前で判別されます:
|
||||
|
||||
{* ../../docs_src/query_params/tutorial004.py hl[8,10] *}
|
||||
{* ../../docs_src/query_params/tutorial004_py310.py hl[6,8] *}
|
||||
|
||||
## 必須のクエリパラメータ
|
||||
## 必須のクエリパラメータ { #required-query-parameters }
|
||||
|
||||
パスパラメータ以外のパラメータ (今のところ、クエリパラメータのみ説明しました) のデフォルト値を宣言した場合、そのパラメータは必須ではなくなります。
|
||||
パスパラメータ以外のパラメータ (今のところ、クエリパラメータのみ見てきました) のデフォルト値を宣言した場合、そのパラメータは必須ではなくなります。
|
||||
|
||||
特定の値を与えずにただオプショナルにしたい場合はデフォルト値を `None` にして下さい。
|
||||
|
||||
しかしクエリパラメータを必須にしたい場合は、ただデフォルト値を宣言しなければよいです:
|
||||
|
||||
{* ../../docs_src/query_params/tutorial005.py hl[6:7] *}
|
||||
{* ../../docs_src/query_params/tutorial005_py39.py hl[6:7] *}
|
||||
|
||||
ここで、クエリパラメータ `needy` は `str` 型の必須のクエリパラメータです
|
||||
ここで、クエリパラメータ `needy` は `str` 型の必須のクエリパラメータです。
|
||||
|
||||
以下のURLをブラウザで開くと:
|
||||
|
||||
@@ -141,16 +142,17 @@ http://127.0.0.1:8000/items/foo-item
|
||||
|
||||
```JSON
|
||||
{
|
||||
"detail": [
|
||||
{
|
||||
"loc": [
|
||||
"query",
|
||||
"needy"
|
||||
],
|
||||
"msg": "field required",
|
||||
"type": "value_error.missing"
|
||||
}
|
||||
]
|
||||
"detail": [
|
||||
{
|
||||
"type": "missing",
|
||||
"loc": [
|
||||
"query",
|
||||
"needy"
|
||||
],
|
||||
"msg": "Field required",
|
||||
"input": null
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -169,9 +171,9 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
|
||||
}
|
||||
```
|
||||
|
||||
そして当然、あるパラメータを必須に、別のパラメータにデフォルト値を設定し、また別のパラメータをオプショナルにできます:
|
||||
そして当然、あるパラメータを必須に、あるパラメータにデフォルト値を設定し、またあるパラメータを完全にオプショナルにできます:
|
||||
|
||||
{* ../../docs_src/query_params/tutorial006.py hl[10] *}
|
||||
{* ../../docs_src/query_params/tutorial006_py310.py hl[8] *}
|
||||
|
||||
この場合、3つのクエリパラメータがあります。:
|
||||
|
||||
@@ -181,6 +183,6 @@ http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
[パスパラメータ](path-params.md#_8){.internal-link target=_blank}と同様に `Enum` を使用できます。
|
||||
[パスパラメータ](path-params.md#predefined-values){.internal-link target=_blank}と同様に `Enum` を使用できます。
|
||||
|
||||
///
|
||||
|
||||
@@ -1,24 +1,28 @@
|
||||
# リクエストフォームとファイル
|
||||
# リクエストフォームとファイル { #request-forms-and-files }
|
||||
|
||||
`File`と`Form`を同時に使うことでファイルとフォームフィールドを定義することができます。
|
||||
|
||||
/// info | 情報
|
||||
|
||||
アップロードされたファイルやフォームデータを受信するには、まず<a href="https://andrew-d.github.io/python-multipart/" class="external-link" target="_blank">`python-multipart`</a>をインストールします。
|
||||
アップロードされたファイルやフォームデータを受信するには、まず<a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>をインストールします。
|
||||
|
||||
例えば、`pip install python-multipart`のように。
|
||||
[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成し、それを有効化してから、例えば次のようにインストールしてください:
|
||||
|
||||
```console
|
||||
$ pip install python-multipart
|
||||
```
|
||||
|
||||
///
|
||||
|
||||
## `File`と`Form`のインポート
|
||||
## `File`と`Form`のインポート { #import-file-and-form }
|
||||
|
||||
{* ../../docs_src/request_forms_and_files/tutorial001.py hl[1] *}
|
||||
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[3] *}
|
||||
|
||||
## `File`と`Form`のパラメータの定義
|
||||
## `File`と`Form`のパラメータの定義 { #define-file-and-form-parameters }
|
||||
|
||||
ファイルやフォームのパラメータは`Body`や`Query`の場合と同じように作成します:
|
||||
|
||||
{* ../../docs_src/request_forms_and_files/tutorial001.py hl[8] *}
|
||||
{* ../../docs_src/request_forms_and_files/tutorial001_an_py39.py hl[10:12] *}
|
||||
|
||||
ファイルとフォームフィールドがフォームデータとしてアップロードされ、ファイルとフォームフィールドを受け取ります。
|
||||
|
||||
@@ -32,6 +36,6 @@
|
||||
|
||||
///
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
同じリクエストでデータやファイルを受け取る必要がある場合は、`File` と`Form`を一緒に使用します。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# フォームデータ
|
||||
# フォームデータ { #form-data }
|
||||
|
||||
JSONの代わりにフィールドを受け取る場合は、`Form`を使用します。
|
||||
|
||||
@@ -6,27 +6,31 @@ JSONの代わりにフィールドを受け取る場合は、`Form`を使用し
|
||||
|
||||
フォームを使うためには、まず<a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>をインストールします。
|
||||
|
||||
たとえば、`pip install python-multipart`のように。
|
||||
必ず[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成して有効化してから、例えば次のようにインストールしてください:
|
||||
|
||||
```console
|
||||
$ pip install python-multipart
|
||||
```
|
||||
|
||||
///
|
||||
|
||||
## `Form`のインポート
|
||||
## `Form`のインポート { #import-form }
|
||||
|
||||
`fastapi`から`Form`をインポートします:
|
||||
|
||||
{* ../../docs_src/request_forms/tutorial001.py hl[1] *}
|
||||
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[3] *}
|
||||
|
||||
## `Form`のパラメータの定義
|
||||
## `Form`のパラメータの定義 { #define-form-parameters }
|
||||
|
||||
`Body`や`Query`の場合と同じようにフォームパラメータを作成します:
|
||||
|
||||
{* ../../docs_src/request_forms/tutorial001.py hl[7] *}
|
||||
{* ../../docs_src/request_forms/tutorial001_an_py39.py hl[9] *}
|
||||
|
||||
例えば、OAuth2仕様が使用できる方法の1つ(「パスワードフロー」と呼ばれる)では、フォームフィールドとして`username`と`password`を送信する必要があります。
|
||||
|
||||
<abbr title="仕様">仕様</abbr>では、フィールドの名前が`username`と`password`であることと、JSONではなくフォームフィールドとして送信されることを要求しています。
|
||||
<abbr title="specification – 仕様">spec</abbr>では、フィールドの名前が`username`と`password`であることと、JSONではなくフォームフィールドとして送信されることを要求しています。
|
||||
|
||||
`Form`では`Body`(および`Query`や`Path`、`Cookie`)と同じメタデータとバリデーションを宣言することができます。
|
||||
`Form`では`Body`(および`Query`や`Path`、`Cookie`)と同じ設定を宣言することができます。これには、バリデーション、例、エイリアス(例えば`username`の代わりに`user-name`)などが含まれます。
|
||||
|
||||
/// info | 情報
|
||||
|
||||
@@ -40,7 +44,7 @@ JSONの代わりにフィールドを受け取る場合は、`Form`を使用し
|
||||
|
||||
///
|
||||
|
||||
## 「フォームフィールド」について
|
||||
## 「フォームフィールド」について { #about-form-fields }
|
||||
|
||||
HTMLフォーム(`<form></form>`)がサーバにデータを送信する方法は、通常、そのデータに「特別な」エンコーディングを使用していますが、これはJSONとは異なります。
|
||||
|
||||
@@ -64,6 +68,6 @@ HTMLフォーム(`<form></form>`)がサーバにデータを送信する方
|
||||
|
||||
///
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
フォームデータの入力パラメータを宣言するには、`Form`を使用する。
|
||||
|
||||
@@ -1,6 +1,35 @@
|
||||
# レスポンスモデル
|
||||
# レスポンスモデル - 戻り値の型 { #response-model-return-type }
|
||||
|
||||
*path operations* のいずれにおいても、`response_model`パラメータを使用して、レスポンスのモデルを宣言することができます:
|
||||
*path operation 関数*の**戻り値の型**にアノテーションを付けることで、レスポンスに使用される型を宣言できます。
|
||||
|
||||
関数**パラメータ**の入力データと同じように **型アノテーション** を使用できます。Pydanticモデル、リスト、辞書、整数や真偽値などのスカラー値を使用できます。
|
||||
|
||||
{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *}
|
||||
|
||||
FastAPIはこの戻り値の型を使って以下を行います:
|
||||
|
||||
* 返却データを**検証**します。
|
||||
* データが不正(例: フィールドが欠けている)であれば、それは*あなた*のアプリコードが壊れていて、返すべきものを返していないことを意味し、不正なデータを返す代わりにサーバーエラーを返します。これにより、あなたとクライアントは、期待されるデータとデータ形状を受け取れることを確実にできます。
|
||||
* OpenAPIの *path operation* に、レスポンス用の **JSON Schema** を追加します。
|
||||
* これは**自動ドキュメント**で使用されます。
|
||||
* 自動クライアントコード生成ツールでも使用されます。
|
||||
|
||||
しかし、最も重要なのは:
|
||||
|
||||
* 戻り値の型で定義された内容に合わせて、出力データを**制限しフィルタリング**します。
|
||||
* これは**セキュリティ**の観点で特に重要です。以下で詳しく見ていきます。
|
||||
|
||||
## `response_model`パラメータ { #response-model-parameter }
|
||||
|
||||
型が宣言している内容とまったく同じではないデータを返す必要がある、またはそうしたいケースがあります。
|
||||
|
||||
例えば、**辞書を返す**、またはデータベースオブジェクトを返したいが、**Pydanticモデルとして宣言**したい場合があります。こうすることで、Pydanticモデルが返したオブジェクト(例: 辞書やデータベースオブジェクト)のドキュメント化、バリデーションなどをすべて行ってくれます。
|
||||
|
||||
戻り値の型アノテーションを追加すると、ツールやエディタが(正しく)エラーとして、関数が宣言した型(例: Pydanticモデル)とは異なる型(例: dict)を返していると警告します。
|
||||
|
||||
そのような場合、戻り値の型の代わりに、*path operation デコレータ*のパラメータ `response_model` を使用できます。
|
||||
|
||||
`response_model`パラメータは、いずれの *path operation* でも使用できます:
|
||||
|
||||
* `@app.get()`
|
||||
* `@app.post()`
|
||||
@@ -8,104 +37,211 @@
|
||||
* `@app.delete()`
|
||||
* など。
|
||||
|
||||
{* ../../docs_src/response_model/tutorial001.py hl[17] *}
|
||||
{* ../../docs_src/response_model/tutorial001_py310.py hl[17,22,24:27] *}
|
||||
|
||||
/// note | 備考
|
||||
|
||||
`response_model`は「デコレータ」メソッド(`get`、`post`など)のパラメータであることに注意してください。すべてのパラメータやボディのように、*path operation関数* のパラメータではありません。
|
||||
`response_model`は「デコレータ」メソッド(`get`、`post`など)のパラメータであることに注意してください。すべてのパラメータやボディのように、*path operation 関数* のパラメータではありません。
|
||||
|
||||
///
|
||||
|
||||
Pydanticモデルの属性に対して宣言するのと同じ型を受け取るので、Pydanticモデルになることもできますが、例えば、`List[Item]`のようなPydanticモデルの`list`になることもできます。
|
||||
`response_model`は、Pydanticモデルのフィールドで宣言するのと同じ型を受け取ります。そのため、Pydanticモデルにもできますし、例えば `List[Item]` のように、Pydanticモデルの `list` にもできます。
|
||||
|
||||
FastAPIは`response_model`を使って以下のことをします:
|
||||
FastAPIはこの `response_model` を使って、データのドキュメント化や検証などを行い、さらに出力データを型宣言に合わせて**変換・フィルタリング**します。
|
||||
|
||||
* 出力データを型宣言に変換します。
|
||||
* データを検証します。
|
||||
* OpenAPIの *path operation* で、レスポンス用のJSON Schemaを追加します。
|
||||
* 自動ドキュメントシステムで使用されます。
|
||||
/// tip | 豆知識
|
||||
|
||||
しかし、最も重要なのは:
|
||||
エディタやmypyなどで厳密な型チェックをしている場合、関数の戻り値の型を `Any` として宣言できます。
|
||||
|
||||
* 出力データをモデルのデータに限定します。これがどのように重要なのか以下で見ていきましょう。
|
||||
|
||||
/// note | 技術詳細
|
||||
|
||||
レスポンスモデルは、関数の戻り値のアノテーションではなく、このパラメータで宣言されています。なぜなら、パス関数は実際にはそのレスポンスモデルを返すのではなく、`dict`やデータベースオブジェクト、あるいは他のモデルを返し、`response_model`を使用してフィールドの制限やシリアライズを行うからです。
|
||||
そうすると、意図的に何でも返していることをエディタに伝えられます。それでもFastAPIは `response_model` を使って、データのドキュメント化、検証、フィルタリングなどを行います。
|
||||
|
||||
///
|
||||
|
||||
## 同じ入力データの返却
|
||||
### `response_model`の優先順位 { #response-model-priority }
|
||||
|
||||
ここでは`UserIn`モデルを宣言しています。それには平文のパスワードが含まれています:
|
||||
戻り値の型と `response_model` の両方を宣言した場合、`response_model` が優先され、FastAPIで使用されます。
|
||||
|
||||
{* ../../docs_src/response_model/tutorial002.py hl[9,11] *}
|
||||
これにより、レスポンスモデルとは異なる型を返している場合でも、エディタやmypyなどのツールで使用するために関数へ正しい型アノテーションを追加できます。それでもFastAPIは `response_model` を使用してデータの検証やドキュメント化などを実行できます。
|
||||
|
||||
また `response_model=None` を使用して、その*path operation*のレスポンスモデル生成を無効化することもできます。これは、Pydanticのフィールドとして有効ではないものに対して型アノテーションを追加する場合に必要になることがあります。以下のセクションのいずれかで例を示します。
|
||||
|
||||
## 同じ入力データの返却 { #return-the-same-input-data }
|
||||
|
||||
ここでは `UserIn` モデルを宣言しています。これには平文のパスワードが含まれます:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial002_py310.py hl[7,9] *}
|
||||
|
||||
/// info | 情報
|
||||
|
||||
`EmailStr` を使用するには、最初に <a href="https://github.com/JoshData/python-email-validator" class="external-link" target="_blank">`email-validator`</a> をインストールしてください。
|
||||
|
||||
[仮想環境](../virtual-environments.md){.internal-link target=_blank}を作成して有効化してから、例えば次のようにインストールしてください:
|
||||
|
||||
```console
|
||||
$ pip install email-validator
|
||||
```
|
||||
|
||||
または次のようにします:
|
||||
|
||||
```console
|
||||
$ pip install "pydantic[email]"
|
||||
```
|
||||
|
||||
///
|
||||
|
||||
そして、このモデルを使用して入力を宣言し、同じモデルを使って出力を宣言しています:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial002.py hl[17,18] *}
|
||||
{* ../../docs_src/response_model/tutorial002_py310.py hl[16] *}
|
||||
|
||||
これで、ブラウザがパスワードを使ってユーザーを作成する際に、APIがレスポンスで同じパスワードを返すようになりました。
|
||||
|
||||
この場合、ユーザー自身がパスワードを送信しているので問題ないかもしれません。
|
||||
この場合、同じユーザーがパスワードを送信しているので問題ないかもしれません。
|
||||
|
||||
しかし、同じモデルを別の*path operation*に使用すると、すべてのクライアントにユーザーのパスワードを送信してしまうことになります。
|
||||
しかし、同じモデルを別の*path operation*に使用すると、すべてのクライアントにユーザーのパスワードを送信してしまう可能性があります。
|
||||
|
||||
/// danger | 危険
|
||||
/// danger | 警告
|
||||
|
||||
ユーザーの平文のパスワードを保存したり、レスポンスで送信したりすることは絶対にしないでください。
|
||||
すべての注意点を理解していて、自分が何をしているか分かっている場合を除き、ユーザーの平文のパスワードを保存したり、このようにレスポンスで送信したりしないでください。
|
||||
|
||||
///
|
||||
|
||||
## 出力モデルの追加
|
||||
## 出力モデルの追加 { #add-an-output-model }
|
||||
|
||||
代わりに、平文のパスワードを持つ入力モデルと、パスワードを持たない出力モデルを作成することができます:
|
||||
代わりに、平文のパスワードを持つ入力モデルと、パスワードを持たない出力モデルを作成できます:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003.py hl[9,11,16] *}
|
||||
{* ../../docs_src/response_model/tutorial003_py310.py hl[9,11,16] *}
|
||||
|
||||
ここでは、*path operation関数*がパスワードを含む同じ入力ユーザーを返しているにもかかわらず:
|
||||
ここでは、*path operation 関数*がパスワードを含む同じ入力ユーザーを返しているにもかかわらず:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003.py hl[24] *}
|
||||
{* ../../docs_src/response_model/tutorial003_py310.py hl[24] *}
|
||||
|
||||
...`response_model`を`UserOut`と宣言したことで、パスワードが含まれていません:
|
||||
...`response_model`を、パスワードを含まない `UserOut` モデルとして宣言しました:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003.py hl[22] *}
|
||||
{* ../../docs_src/response_model/tutorial003_py310.py hl[22] *}
|
||||
|
||||
そのため、**FastAPI** は出力モデルで宣言されていない全てのデータをフィルタリングしてくれます(Pydanticを使用)。
|
||||
そのため、**FastAPI** は出力モデルで宣言されていないすべてのデータをフィルタリングしてくれます(Pydanticを使用)。
|
||||
|
||||
## ドキュメントを見る
|
||||
### `response_model`または戻り値の型 { #response-model-or-return-type }
|
||||
|
||||
自動ドキュメントを見ると、入力モデルと出力モデルがそれぞれ独自のJSON Schemaを持っていることが確認できます。
|
||||
このケースでは2つのモデルが異なるため、関数の戻り値の型を `UserOut` としてアノテーションすると、エディタやツールは、異なるクラスなので不正な型を返していると警告します。
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/response-model/image01.png">
|
||||
そのため、この例では `response_model` パラメータで宣言する必要があります。
|
||||
|
||||
そして、両方のモデルは、対話型のAPIドキュメントに使用されます:
|
||||
...しかし、これを解決する方法を以下で確認しましょう。
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/response-model/image02.png">
|
||||
## 戻り値の型とデータフィルタリング { #return-type-and-data-filtering }
|
||||
|
||||
## レスポンスモデルのエンコーディングパラメータ
|
||||
前の例から続けます。**関数に1つの型をアノテーション**したい一方で、関数からは実際には**より多くのデータ**を含むものを返せるようにしたいとします。
|
||||
|
||||
レスポンスモデルにはデフォルト値を設定することができます:
|
||||
FastAPIにはレスポンスモデルを使用してデータを**フィルタリング**し続けてほしいです。つまり、関数がより多くのデータを返しても、レスポンスにはレスポンスモデルで宣言されたフィールドのみが含まれます。
|
||||
|
||||
{* ../../docs_src/response_model/tutorial004.py hl[11,13,14] *}
|
||||
前の例ではクラスが異なるため `response_model` パラメータを使う必要がありました。しかしそれは、エディタやツールによる関数の戻り値の型チェックのサポートを受けられないことも意味します。
|
||||
|
||||
* `description: str = None`は`None`がデフォルト値です。
|
||||
* `tax: float = 10.5`は`10.5`がデフォルト値です。
|
||||
* `tags: List[str] = []` は空のリスト(`[]`)がデフォルト値です。
|
||||
しかし、このようなことが必要になる多くのケースでは、この例のようにモデルでデータの一部を**フィルタ/削除**したいだけです。
|
||||
|
||||
しかし、実際に保存されていない場合には結果からそれらを省略した方が良いかもしれません。
|
||||
そのような場合、クラスと継承を利用して関数の**型アノテーション**を活用し、エディタやツールのサポートを改善しつつ、FastAPIの**データフィルタリング**も得られます。
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003_01_py310.py hl[7:10,13:14,18] *}
|
||||
|
||||
これにより、このコードは型として正しいためエディタやmypyからのツール支援を得られますし、FastAPIによるデータフィルタリングも得られます。
|
||||
|
||||
これはどのように動作するのでしょうか?確認してみましょう。🤓
|
||||
|
||||
### 型アノテーションとツール支援 { #type-annotations-and-tooling }
|
||||
|
||||
まず、エディタ、mypy、その他のツールがこれをどう見るかを見てみます。
|
||||
|
||||
`BaseUser` には基本フィールドがあります。次に `UserIn` が `BaseUser` を継承して `password` フィールドを追加するため、両方のモデルのフィールドがすべて含まれます。
|
||||
|
||||
関数の戻り値の型を `BaseUser` としてアノテーションしますが、実際には `UserIn` インスタンスを返しています。
|
||||
|
||||
エディタやmypyなどのツールはこれに文句を言いません。typingの観点では、`UserIn` は `BaseUser` のサブクラスであり、期待されるものが `BaseUser` であれば `UserIn` は*有効*な型だからです。
|
||||
|
||||
### FastAPIのデータフィルタリング { #fastapi-data-filtering }
|
||||
|
||||
一方FastAPIでは、戻り値の型を見て、返す内容にその型で宣言されたフィールド**だけ**が含まれることを確認します。
|
||||
|
||||
FastAPIは、返却データのフィルタリングにクラス継承の同じルールが使われてしまわないようにするため、内部でPydanticを使っていくつかの処理を行っています。そうでないと、期待以上に多くのデータを返してしまう可能性があります。
|
||||
|
||||
この方法で、**ツール支援**付きの型アノテーションと**データフィルタリング**の両方という、いいとこ取りができます。
|
||||
|
||||
## ドキュメントを見る { #see-it-in-the-docs }
|
||||
|
||||
自動ドキュメントを見ると、入力モデルと出力モデルがそれぞれ独自のJSON Schemaを持っていることが確認できます:
|
||||
|
||||
<img src="/img/tutorial/response-model/image01.png">
|
||||
|
||||
そして、両方のモデルは対話型のAPIドキュメントに使用されます:
|
||||
|
||||
<img src="/img/tutorial/response-model/image02.png">
|
||||
|
||||
## その他の戻り値の型アノテーション { #other-return-type-annotations }
|
||||
|
||||
Pydanticフィールドとして有効ではないものを返し、ツール(エディタやmypyなど)が提供するサポートを得るためだけに、関数でそれをアノテーションするケースがあるかもしれません。
|
||||
|
||||
### レスポンスを直接返す { #return-a-response-directly }
|
||||
|
||||
最も一般的なケースは、[高度なドキュメントで後述する「Responseを直接返す」](../advanced/response-directly.md){.internal-link target=_blank}場合です。
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003_02_py39.py hl[8,10:11] *}
|
||||
|
||||
このシンプルなケースは、戻り値の型アノテーションが `Response` のクラス(またはサブクラス)であるため、FastAPIが自動的に処理します。
|
||||
|
||||
また `RedirectResponse` と `JSONResponse` の両方は `Response` のサブクラスなので、ツールも型アノテーションが正しいとして問題にしません。
|
||||
|
||||
### `Response`のサブクラスをアノテーションする { #annotate-a-response-subclass }
|
||||
|
||||
型アノテーションで `Response` のサブクラスを使うこともできます:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003_03_py39.py hl[8:9] *}
|
||||
|
||||
これは `RedirectResponse` が `Response` のサブクラスであり、FastAPIがこのシンプルなケースを自動処理するため、同様に動作します。
|
||||
|
||||
### 無効な戻り値の型アノテーション { #invalid-return-type-annotations }
|
||||
|
||||
しかし、Pydantic型として有効ではない別の任意のオブジェクト(例: データベースオブジェクト)を返し、関数でそのようにアノテーションすると、FastAPIはその型アノテーションからPydanticレスポンスモデルを作成しようとして失敗します。
|
||||
|
||||
同様に、<abbr title='複数の型のunionは「これらの型のいずれか」を意味します。'>union</abbr>のように、複数の型のうち1つ以上がPydantic型として有効でないものを含む場合も起こります。例えば次は失敗します 💥:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003_04_py310.py hl[8] *}
|
||||
|
||||
...これは、型アノテーションがPydantic型ではなく、単一の `Response` クラス(またはサブクラス)でもないために失敗します。`Response` と `dict` の間のunion(どちらか)になっているからです。
|
||||
|
||||
### レスポンスモデルを無効化する { #disable-response-model }
|
||||
|
||||
上の例を続けると、FastAPIが実行するデフォルトのデータ検証、ドキュメント化、フィルタリングなどを行いたくないこともあるでしょう。
|
||||
|
||||
しかし、エディタや型チェッカー(例: mypy)などのツール支援を得るために、関数の戻り値の型アノテーションは残したいかもしれません。
|
||||
|
||||
その場合、`response_model=None` を設定することでレスポンスモデルの生成を無効にできます:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial003_05_py310.py hl[7] *}
|
||||
|
||||
これによりFastAPIはレスポンスモデル生成をスキップし、FastAPIアプリケーションに影響させずに必要な戻り値の型アノテーションを付けられます。🤓
|
||||
|
||||
## レスポンスモデルのエンコーディングパラメータ { #response-model-encoding-parameters }
|
||||
|
||||
レスポンスモデルには次のようにデフォルト値を設定できます:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial004_py310.py hl[9,11:12] *}
|
||||
|
||||
* `description: Union[str, None] = None`(またはPython 3.10では `str | None = None`)はデフォルトが `None` です。
|
||||
* `tax: float = 10.5` はデフォルトが `10.5` です。
|
||||
* `tags: List[str] = []` はデフォルトが空のリスト `[]` です。
|
||||
|
||||
ただし、それらが実際には保存されていない場合、結果から省略したいことがあります。
|
||||
|
||||
例えば、NoSQLデータベースに多くのオプション属性を持つモデルがあるが、デフォルト値でいっぱいの非常に長いJSONレスポンスを送信したくない場合です。
|
||||
|
||||
### `response_model_exclude_unset`パラメータの使用
|
||||
### `response_model_exclude_unset`パラメータの使用 { #use-the-response-model-exclude-unset-parameter }
|
||||
|
||||
*path operation デコレータ*に`response_model_exclude_unset=True`パラメータを設定することができます:
|
||||
*path operation デコレータ*のパラメータ `response_model_exclude_unset=True` を設定できます:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial004.py hl[24] *}
|
||||
{* ../../docs_src/response_model/tutorial004_py310.py hl[22] *}
|
||||
|
||||
そして、これらのデフォルト値はレスポンスに含まれず、実際に設定された値のみが含まれます。
|
||||
そうすると、デフォルト値はレスポンスに含まれず、実際に設定された値のみが含まれます。
|
||||
|
||||
そのため、*path operation*にID`foo`が設定されたitemのリクエストを送ると、レスポンスは以下のようになります(デフォルト値を含まない):
|
||||
そのため、ID `foo` のitemに対してその *path operation* へリクエストを送ると、レスポンスは以下のようになります(デフォルト値を含まない):
|
||||
|
||||
```JSON
|
||||
{
|
||||
@@ -116,26 +252,20 @@ FastAPIは`response_model`を使って以下のことをします:
|
||||
|
||||
/// info | 情報
|
||||
|
||||
FastAPIはこれをするために、Pydanticモデルの`.dict()`を<a href="https://docs.pydantic.dev/latest/concepts/serialization/#modeldict" class="external-link" target="_blank">その`exclude_unset`パラメータ</a>で使用しています。
|
||||
|
||||
///
|
||||
|
||||
/// info | 情報
|
||||
|
||||
以下も使用することができます:
|
||||
以下も使用できます:
|
||||
|
||||
* `response_model_exclude_defaults=True`
|
||||
* `response_model_exclude_none=True`
|
||||
|
||||
`exclude_defaults`と`exclude_none`については、<a href="https://docs.pydantic.dev/latest/concepts/serialization/#modeldict" class="external-link" target="_blank">Pydanticのドキュメント</a>で説明されている通りです。
|
||||
`exclude_defaults` と `exclude_none` については、<a href="https://docs.pydantic.dev/1.10/usage/exporting_models/#modeldict" class="external-link" target="_blank">Pydanticのドキュメント</a>で説明されている通りです。
|
||||
|
||||
///
|
||||
|
||||
#### デフォルト値を持つフィールドの値を持つデータ
|
||||
#### デフォルト値を持つフィールドに値があるデータ { #data-with-values-for-fields-with-defaults }
|
||||
|
||||
しかし、ID`bar`のitemのように、デフォルト値が設定されているモデルのフィールドに値が設定されている場合:
|
||||
しかし、ID `bar` のitemのように、デフォルト値が設定されているモデルのフィールドに値が設定されている場合:
|
||||
|
||||
```Python hl_lines="3 5"
|
||||
```Python hl_lines="3 5"
|
||||
{
|
||||
"name": "Bar",
|
||||
"description": "The bartenders",
|
||||
@@ -146,11 +276,11 @@ FastAPIはこれをするために、Pydanticモデルの`.dict()`を<a href="ht
|
||||
|
||||
それらはレスポンスに含まれます。
|
||||
|
||||
#### デフォルト値と同じ値を持つデータ
|
||||
#### デフォルト値と同じ値を持つデータ { #data-with-the-same-values-as-the-defaults }
|
||||
|
||||
ID`baz`のitemのようにデフォルト値と同じ値を持つデータの場合:
|
||||
ID `baz` のitemのようにデフォルト値と同じ値を持つデータの場合:
|
||||
|
||||
```Python hl_lines="3 5 6"
|
||||
```Python hl_lines="3 5-6"
|
||||
{
|
||||
"name": "Baz",
|
||||
"description": None,
|
||||
@@ -160,53 +290,54 @@ ID`baz`のitemのようにデフォルト値と同じ値を持つデータの場
|
||||
}
|
||||
```
|
||||
|
||||
FastAPIは十分に賢いので(実際には、Pydanticが十分に賢い)`description`や`tax`、`tags`はデフォルト値と同じ値を持っているにもかかわらず、明示的に設定されていることを理解しています。(デフォルトから取得するのではなく)
|
||||
FastAPIは十分に賢いので(実際には、Pydanticが十分に賢い)、`description` や `tax`、`tags` がデフォルト値と同じ値であっても、明示的に設定された(デフォルトから取得されたのではない)ことを理解します。
|
||||
|
||||
そのため、それらはJSONレスポンスに含まれることになります。
|
||||
そのため、それらはJSONレスポンスに含まれます。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
デフォルト値は`None`だけでなく、なんでも良いことに注意してください。
|
||||
例えば、リスト(`[]`)や`10.5`の`float`などです。
|
||||
デフォルト値は `None` だけではないことに注意してください。
|
||||
|
||||
リスト(`[]`)や `10.5` の `float` などでも構いません。
|
||||
|
||||
///
|
||||
|
||||
### `response_model_include`と`response_model_exclude`
|
||||
### `response_model_include`と`response_model_exclude` { #response-model-include-and-response-model-exclude }
|
||||
|
||||
*path operationデコレータ*として`response_model_include`と`response_model_exclude`も使用することができます。
|
||||
*path operation デコレータ*のパラメータ `response_model_include` と `response_model_exclude` も使用できます。
|
||||
|
||||
属性名を持つ`str`の`set`を受け取り、含める(残りを省略する)か、除外(残りを含む)します。
|
||||
これらは、含める(残りを省略する)または除外する(残りを含む)属性名を持つ `str` の `set` を受け取ります。
|
||||
|
||||
これは、Pydanticモデルが1つしかなく、出力からいくつかのデータを削除したい場合のクイックショートカットとして使用することができます。
|
||||
これは、Pydanticモデルが1つしかなく、出力からいくつかのデータを削除したい場合のクイックショートカットとして使用できます。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
それでも、これらのパラメータではなく、複数のクラスを使用して、上記のようなアイデアを使うことをおすすめします。
|
||||
それでも、これらのパラメータではなく、上で示したアイデアのように複数のクラスを使うことが推奨されます。
|
||||
|
||||
これは`response_model_include`や`response_mode_exclude`を使用していくつかの属性を省略しても、アプリケーションのOpenAPI(とドキュメント)で生成されたJSON Schemaが完全なモデルになるからです。
|
||||
これは、`response_model_include` や `response_model_exclude` を使っていくつかの属性を省略しても、アプリのOpenAPI(とドキュメント)で生成されるJSON Schemaが完全なモデルのままになるためです。
|
||||
|
||||
同様に動作する`response_model_by_alias`にも当てはまります。
|
||||
同様に動作する `response_model_by_alias` にも当てはまります。
|
||||
|
||||
///
|
||||
|
||||
{* ../../docs_src/response_model/tutorial005.py hl[31,37] *}
|
||||
{* ../../docs_src/response_model/tutorial005_py310.py hl[29,35] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
`{"name", "description"}`の構文はこれら2つの値をもつ`set`を作成します。
|
||||
`{"name", "description"}` の構文は、それら2つの値を持つ `set` を作成します。
|
||||
|
||||
これは`set(["name", "description"])`と同等です。
|
||||
これは `set(["name", "description"])` と同等です。
|
||||
|
||||
///
|
||||
|
||||
#### `set`の代わりに`list`を使用する
|
||||
#### `set`の代わりに`list`を使用する { #using-lists-instead-of-sets }
|
||||
|
||||
もし`set`を使用することを忘れて、代わりに`list`や`tuple`を使用しても、FastAPIはそれを`set`に変換して正しく動作します:
|
||||
もし `set` を使用することを忘れて、代わりに `list` や `tuple` を使用しても、FastAPIはそれを `set` に変換して正しく動作します:
|
||||
|
||||
{* ../../docs_src/response_model/tutorial006.py hl[31,37] *}
|
||||
{* ../../docs_src/response_model/tutorial006_py310.py hl[29,35] *}
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
*path operationデコレータの*`response_model`パラメータを使用して、レスポンスモデルを定義し、特にプライベートデータがフィルタリングされていることを保証します。
|
||||
*path operation デコレータ*のパラメータ `response_model` を使用してレスポンスモデルを定義し、とくにプライベートデータがフィルタリングされることを保証します。
|
||||
|
||||
明示的に設定された値のみを返すには、`response_model_exclude_unset`を使用します。
|
||||
明示的に設定された値のみを返すには、`response_model_exclude_unset` を使用します。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# レスポンスステータスコード
|
||||
# レスポンスステータスコード { #response-status-code }
|
||||
|
||||
レスポンスモデルを指定するのと同じ方法で、レスポンスに使用されるHTTPステータスコードを以下の*path operations*のいずれかの`status_code`パラメータで宣言することもできます。
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
* `@app.post()`
|
||||
* `@app.put()`
|
||||
* `@app.delete()`
|
||||
* など。
|
||||
* etc.
|
||||
|
||||
{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
|
||||
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
|
||||
|
||||
/// note | 備考
|
||||
|
||||
`status_code`は「デコレータ」メソッド(`get`、`post`など)のパラメータであることに注意してください。すべてのパラメータやボディのように、*path operation関数*のものではありません。
|
||||
`status_code`は「デコレータ」メソッド(`get`、`post`など)のパラメータであることに注意してください。すべてのパラメータやボディのように、*path operation function*のものではありません。
|
||||
|
||||
///
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
* レスポンスでステータスコードを返します。
|
||||
* OpenAPIスキーマ(およびユーザーインターフェース)に以下のように文書化します:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/response-status-code/image01.png">
|
||||
<img src="/img/tutorial/response-status-code/image01.png">
|
||||
|
||||
/// note | 備考
|
||||
|
||||
@@ -39,7 +39,7 @@ FastAPIはこれを知っていて、レスポンスボディがないというO
|
||||
|
||||
///
|
||||
|
||||
## HTTPステータスコードについて
|
||||
## HTTPステータスコードについて { #about-http-status-codes }
|
||||
|
||||
/// note | 備考
|
||||
|
||||
@@ -47,34 +47,34 @@ FastAPIはこれを知っていて、レスポンスボディがないというO
|
||||
|
||||
///
|
||||
|
||||
HTTPでは、レスポンスの一部として3桁の数字のステータスコードを送信します。
|
||||
HTTPでは、レスポンスの一部として3桁の数字のステータスコードを送信します。
|
||||
|
||||
これらのステータスコードは、それらを認識するために関連付けられた名前を持っていますが、重要な部分は番号です。
|
||||
|
||||
つまり:
|
||||
|
||||
* `100`以上は「情報」のためのものです。。直接使うことはほとんどありません。これらのステータスコードを持つレスポンスはボディを持つことができません。
|
||||
* **`200`** 以上は「成功」のレスポンスのためのものです。これらは最も利用するであろうものです。
|
||||
* `100 - 199` は「情報」のためのものです。直接使うことはほとんどありません。これらのステータスコードを持つレスポンスはボディを持つことができません。
|
||||
* **`200 - 299`** は「成功」のレスポンスのためのものです。これらは最も利用するであろうものです。
|
||||
* `200`はデフォルトのステータスコードで、すべてが「OK」であったことを意味します。
|
||||
* 別の例としては、`201`(Created)があります。これはデータベースに新しいレコードを作成した後によく使用されます。
|
||||
* 特殊なケースとして、`204`(No Content)があります。このレスポンスはクライアントに返すコンテンツがない場合に使用されます。そしてこのレスポンスはボディを持つことはできません。
|
||||
* **`300`** 以上は「リダイレクト」のためのものです。これらのステータスコードを持つレスポンスは`304`(Not Modified)を除き、ボディを持つことも持たないこともできます。
|
||||
* **`400`** 以上は「クライアントエラー」のレスポンスのためのものです。これらは、おそらく最も多用するであろう2番目のタイプです。
|
||||
* 特殊なケースとして、`204`(No Content)があります。このレスポンスはクライアントに返すコンテンツがない場合に使用されるため、レスポンスはボディを持ってはいけません。
|
||||
* **`300 - 399`** は「リダイレクト」のためのものです。これらのステータスコードを持つレスポンスは`304`(Not Modified)を除き、ボディを持つことも持たないこともできます。`304`はボディを持ってはいけません。
|
||||
* **`400 - 499`** は「クライアントエラー」のレスポンスのためのものです。これらは、おそらく最も多用するであろう2番目のタイプです。
|
||||
* 例えば、`404`は「Not Found」レスポンスです。
|
||||
* クライアントからの一般的なエラーについては、`400`を使用することができます。
|
||||
* `500`以上はサーバーエラーのためのものです。これらを直接使うことはほとんどありません。アプリケーションコードやサーバーのどこかで何か問題が発生した場合、これらのステータスコードのいずれかが自動的に返されます。
|
||||
* `500 - 599` はサーバーエラーのためのものです。これらを直接使うことはほとんどありません。アプリケーションコードやサーバーのどこかで何か問題が発生した場合、これらのステータスコードのいずれかが自動的に返されます。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
それぞれのステータスコードとどのコードが何のためのコードなのかについて詳細は<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> HTTP レスポンスステータスコードについてのドキュメント</a>を参照してください。
|
||||
それぞれのステータスコードとどのコードが何のためのコードなのかについて詳細は<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" class="external-link" target="_blank"><abbr title="Mozilla Developer Network">MDN</abbr> documentation about HTTP status codes</a>を参照してください。
|
||||
|
||||
///
|
||||
|
||||
## 名前を覚えるための近道
|
||||
## 名前を覚えるための近道 { #shortcut-to-remember-the-names }
|
||||
|
||||
先ほどの例をもう一度見てみましょう:
|
||||
|
||||
{* ../../docs_src/response_status_code/tutorial001.py hl[6] *}
|
||||
{* ../../docs_src/response_status_code/tutorial001_py39.py hl[6] *}
|
||||
|
||||
`201`は「作成完了」のためのステータスコードです。
|
||||
|
||||
@@ -82,11 +82,11 @@ HTTPでは、レスポンスの一部として3桁の数字のステータス
|
||||
|
||||
`fastapi.status`の便利な変数を利用することができます。
|
||||
|
||||
{* ../../docs_src/response_status_code/tutorial002.py hl[1,6] *}
|
||||
{* ../../docs_src/response_status_code/tutorial002_py39.py hl[1,6] *}
|
||||
|
||||
それらは便利です。それらは同じ番号を保持しており、その方法ではエディタの自動補完を使用してそれらを見つけることができます。
|
||||
それらは単なる便利なものであり、同じ番号を保持しています。しかし、その方法ではエディタの自動補完を使用してそれらを見つけることができます。
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/response-status-code/image02.png">
|
||||
<img src="/img/tutorial/response-status-code/image02.png">
|
||||
|
||||
/// note | 技術詳細
|
||||
|
||||
@@ -96,6 +96,6 @@ HTTPでは、レスポンスの一部として3桁の数字のステータス
|
||||
|
||||
///
|
||||
|
||||
## デフォルトの変更
|
||||
## デフォルトの変更 { #changing-the-default }
|
||||
|
||||
後に、[高度なユーザーガイド](../advanced/response-change-status-code.md){.internal-link target=_blank}で、ここで宣言しているデフォルトとは異なるステータスコードを返す方法を見ていきます。
|
||||
|
||||
@@ -1,55 +1,202 @@
|
||||
# スキーマの追加 - 例
|
||||
# リクエストのExampleデータの宣言 { #declare-request-example-data }
|
||||
|
||||
JSON Schemaに追加する情報を定義することができます。
|
||||
アプリが受け取れるデータの例を宣言できます。
|
||||
|
||||
一般的なユースケースはこのドキュメントで示されているように`example`を追加することです。
|
||||
ここでは、それを行ういくつかの方法を紹介します。
|
||||
|
||||
JSON Schemaの追加情報を宣言する方法はいくつかあります。
|
||||
## Pydanticモデルでの追加JSON Schemaデータ { #extra-json-schema-data-in-pydantic-models }
|
||||
|
||||
## Pydanticの`schema_extra`
|
||||
生成されるJSON Schemaに追加されるPydanticモデルの`examples`を宣言できます。
|
||||
|
||||
<a href="https://docs.pydantic.dev/latest/concepts/json_schema/#schema-customization" class="external-link" target="_blank">Pydanticのドキュメント: スキーマのカスタマイズ</a>で説明されているように、`Config`と`schema_extra`を使ってPydanticモデルの例を宣言することができます:
|
||||
{* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *}
|
||||
|
||||
{* ../../docs_src/schema_extra_example/tutorial001.py hl[15,16,17,18,19,20,21,22,23] *}
|
||||
その追加情報は、そのモデルの出力**JSON Schema**にそのまま追加され、APIドキュメントで使用されます。
|
||||
|
||||
その追加情報はそのまま出力され、JSON Schemaに追加されます。
|
||||
<a href="https://docs.pydantic.dev/latest/api/config/" class="external-link" target="_blank">Pydanticのドキュメント: Configuration</a>で説明されているように、`dict`を受け取る属性`model_config`を使用できます。
|
||||
|
||||
## `Field`の追加引数
|
||||
生成されるJSON Schemaに表示したい追加データ(`examples`を含む)を含む`dict`を使って、`"json_schema_extra"`を設定できます。
|
||||
|
||||
後述する`Field`、`Path`、`Query`、`Body`などでは、任意の引数を関数に渡すことでJSON Schemaの追加情報を宣言することもできます:
|
||||
/// tip | 豆知識
|
||||
|
||||
{* ../../docs_src/schema_extra_example/tutorial002.py hl[4,10,11,12,13] *}
|
||||
同じ手法を使ってJSON Schemaを拡張し、独自のカスタム追加情報を追加できます。
|
||||
|
||||
/// warning | 注意
|
||||
|
||||
これらの追加引数が渡されても、文書化のためのバリデーションは追加されず、注釈だけが追加されることを覚えておいてください。
|
||||
例えば、フロントエンドのユーザーインターフェースのためのメタデータを追加する、などに使えます。
|
||||
|
||||
///
|
||||
|
||||
## `Body`の追加引数
|
||||
/// info | 情報
|
||||
|
||||
追加情報を`Field`に渡すのと同じように、`Path`、`Query`、`Body`などでも同じことができます。
|
||||
OpenAPI 3.1.0(FastAPI 0.99.0以降で使用)では、**JSON Schema**標準の一部である`examples`がサポートされました。
|
||||
|
||||
例えば、`Body`にボディリクエストの`example`を渡すことができます:
|
||||
それ以前は、単一の例を持つキーワード`example`のみがサポートされていました。これはOpenAPI 3.1.0でも引き続きサポートされていますが、非推奨であり、JSON Schema標準の一部ではありません。そのため、`example`から`examples`への移行が推奨されます。🤓
|
||||
|
||||
{* ../../docs_src/schema_extra_example/tutorial003.py hl[21,22,23,24,25,26] *}
|
||||
詳細はこのページの最後で読めます。
|
||||
|
||||
## ドキュメントのUIの例
|
||||
///
|
||||
|
||||
## `Field`の追加引数 { #field-additional-arguments }
|
||||
|
||||
Pydanticモデルで`Field()`を使う場合、追加の`examples`も宣言できます:
|
||||
|
||||
{* ../../docs_src/schema_extra_example/tutorial002_py310.py hl[2,8:11] *}
|
||||
|
||||
## JSON Schema内の`examples` - OpenAPI { #examples-in-json-schema-openapi }
|
||||
|
||||
以下のいずれかを使用する場合:
|
||||
|
||||
* `Path()`
|
||||
* `Query()`
|
||||
* `Header()`
|
||||
* `Cookie()`
|
||||
* `Body()`
|
||||
* `Form()`
|
||||
* `File()`
|
||||
|
||||
追加情報を含む`examples`のグループを宣言でき、それらは**OpenAPI**内のそれぞれの**JSON Schemas**に追加されます。
|
||||
|
||||
### `examples`を使う`Body` { #body-with-examples }
|
||||
|
||||
ここでは、`Body()`で期待されるデータの例を1つ含む`examples`を渡します:
|
||||
|
||||
{* ../../docs_src/schema_extra_example/tutorial003_an_py310.py hl[22:29] *}
|
||||
|
||||
### ドキュメントUIでの例 { #example-in-the-docs-ui }
|
||||
|
||||
上記のいずれの方法でも、`/docs`の中では以下のようになります:
|
||||
|
||||
<img src="https://fastapi.tiangolo.com/img/tutorial/body-fields/image01.png">
|
||||
<img src="/img/tutorial/body-fields/image01.png">
|
||||
|
||||
## 技術詳細
|
||||
### 複数の`examples`を使う`Body` { #body-with-multiple-examples }
|
||||
|
||||
`example` と `examples`について...
|
||||
もちろん、複数の`examples`を渡すこともできます:
|
||||
|
||||
JSON Schemaの最新バージョンでは<a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a>というフィールドを定義していますが、OpenAPIは`examples`を持たない古いバージョンのJSON Schemaをベースにしています。
|
||||
{* ../../docs_src/schema_extra_example/tutorial004_an_py310.py hl[23:38] *}
|
||||
|
||||
そのため、OpenAPIでは同じ目的のために<a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.3.md#fixed-fields-20" class="external-link" target="_blank">`example`</a>を独自に定義しており(`examples`ではなく`example`として)、それがdocs UI(Swagger UIを使用)で使用されています。
|
||||
この場合、examplesはそのボディデータの内部**JSON Schema**の一部になります。
|
||||
|
||||
つまり、`example`はJSON Schemaの一部ではありませんが、OpenAPIの一部であり、それがdocs UIで使用されることになります。
|
||||
それでも、<abbr title="2023-08-26">執筆時点</abbr>では、ドキュメントUIの表示を担当するツールであるSwagger UIは、**JSON Schema**内のデータに対して複数の例を表示することをサポートしていません。しかし、回避策については以下を読んでください。
|
||||
|
||||
## その他の情報
|
||||
### OpenAPI固有の`examples` { #openapi-specific-examples }
|
||||
|
||||
同じように、フロントエンドのユーザーインターフェースなどをカスタマイズするために、各モデルのJSON Schemaに追加される独自の追加情報を追加することができます。
|
||||
**JSON Schema**が`examples`をサポートする前から、OpenAPIは同じく`examples`という別のフィールドをサポートしていました。
|
||||
|
||||
この**OpenAPI固有**の`examples`は、OpenAPI仕様の別のセクションに入ります。各JSON Schemaの中ではなく、**各*path operation*の詳細**に入ります。
|
||||
|
||||
そしてSwagger UIは、この特定の`examples`フィールドを以前からサポートしています。そのため、これを使って**ドキュメントUIに異なる例を表示**できます。
|
||||
|
||||
このOpenAPI固有フィールド`examples`の形は**複数の例**(`list`ではなく)を持つ`dict`であり、それぞれに追加情報が含まれ、その追加情報は**OpenAPI**にも追加されます。
|
||||
|
||||
これはOpenAPIに含まれる各JSON Schemaの中には入らず、外側の、*path operation*に直接入ります。
|
||||
|
||||
### `openapi_examples`パラメータの使用 { #using-the-openapi-examples-parameter }
|
||||
|
||||
FastAPIでは、以下に対してパラメータ`openapi_examples`を使って、OpenAPI固有の`examples`を宣言できます:
|
||||
|
||||
* `Path()`
|
||||
* `Query()`
|
||||
* `Header()`
|
||||
* `Cookie()`
|
||||
* `Body()`
|
||||
* `Form()`
|
||||
* `File()`
|
||||
|
||||
`dict`のキーは各例を識別し、各値は別の`dict`です。
|
||||
|
||||
`examples`内の各特定の例`dict`には、次の内容を含められます:
|
||||
|
||||
* `summary`: 例の短い説明。
|
||||
* `description`: Markdownテキストを含められる長い説明。
|
||||
* `value`: 実際に表示される例(例: `dict`)。
|
||||
* `externalValue`: `value`の代替で、例を指すURLです。ただし、`value`ほど多くのツールでサポートされていない可能性があります。
|
||||
|
||||
次のように使えます:
|
||||
|
||||
{* ../../docs_src/schema_extra_example/tutorial005_an_py310.py hl[23:49] *}
|
||||
|
||||
### ドキュメントUIのOpenAPI Examples { #openapi-examples-in-the-docs-ui }
|
||||
|
||||
`Body()`に`openapi_examples`を追加すると、`/docs`は次のようになります:
|
||||
|
||||
<img src="/img/tutorial/body-fields/image02.png">
|
||||
|
||||
## 技術詳細 { #technical-details }
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
すでに**FastAPI**バージョン**0.99.0以上**を使用している場合、おそらくこれらの詳細は**スキップ**できます。
|
||||
|
||||
これらは、OpenAPI 3.1.0が利用可能になる前の古いバージョンにより関連します。
|
||||
|
||||
これは簡単なOpenAPIとJSON Schemaの**歴史の授業**だと考えられます。🤓
|
||||
|
||||
///
|
||||
|
||||
/// warning | 注意
|
||||
|
||||
ここでは、標準である**JSON Schema**と**OpenAPI**についての非常に技術的な詳細を扱います。
|
||||
|
||||
上のアイデアがすでにうまく動いているなら、それで十分かもしれませんし、おそらくこの詳細は不要です。気軽にスキップしてください。
|
||||
|
||||
///
|
||||
|
||||
OpenAPI 3.1.0より前は、OpenAPIは古く改変されたバージョンの**JSON Schema**を使用していました。
|
||||
|
||||
JSON Schemaには`examples`がなかったため、OpenAPIは自身が改変したバージョンに独自の`example`フィールドを追加しました。
|
||||
|
||||
OpenAPIは、仕様の他の部分にも`example`と`examples`フィールドを追加しました:
|
||||
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#parameter-object" class="external-link" target="_blank">`Parameter Object`(仕様内)</a>。FastAPIの以下で使用されました:
|
||||
* `Path()`
|
||||
* `Query()`
|
||||
* `Header()`
|
||||
* `Cookie()`
|
||||
* <a href="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#media-type-object" class="external-link" target="_blank">`Request Body Object`。仕様内の`Media Type Object`の`content`フィールド(仕様内)</a>。FastAPIの以下で使用されました:
|
||||
* `Body()`
|
||||
* `File()`
|
||||
* `Form()`
|
||||
|
||||
/// info | 情報
|
||||
|
||||
この古いOpenAPI固有の`examples`パラメータは、FastAPI `0.103.0`以降は`openapi_examples`になりました。
|
||||
|
||||
///
|
||||
|
||||
### JSON Schemaの`examples`フィールド { #json-schemas-examples-field }
|
||||
|
||||
しかしその後、JSON Schemaは新しいバージョンの仕様に<a href="https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.5" class="external-link" target="_blank">`examples`</a>フィールドを追加しました。
|
||||
|
||||
そして、新しいOpenAPI 3.1.0は、この新しいフィールド`examples`を含む最新バージョン(JSON Schema 2020-12)に基づくようになりました。
|
||||
|
||||
そして現在、この新しい`examples`フィールドは、古い単一(かつカスタム)の`example`フィールドより優先され、`example`は現在非推奨です。
|
||||
|
||||
JSON Schemaのこの新しい`examples`フィールドは、OpenAPIの他の場所(上で説明)にあるような追加メタデータを持つdictではなく、**単なる例の`list`**です。
|
||||
|
||||
/// info | 情報
|
||||
|
||||
OpenAPI 3.1.0がこのJSON Schemaとの新しいよりシンプルな統合とともにリリースされた後も、しばらくの間、自動ドキュメントを提供するツールであるSwagger UIはOpenAPI 3.1.0をサポートしていませんでした(バージョン5.0.0からサポートされています🎉)。
|
||||
|
||||
そのため、FastAPI 0.99.0より前のバージョンは、OpenAPI 3.1.0より低いバージョンのOpenAPIをまだ使用していました。
|
||||
|
||||
///
|
||||
|
||||
### PydanticとFastAPIの`examples` { #pydantic-and-fastapi-examples }
|
||||
|
||||
Pydanticモデル内で、`schema_extra`または`Field(examples=["something"])`を使って`examples`を追加すると、その例はそのPydanticモデルの**JSON Schema**に追加されます。
|
||||
|
||||
そしてそのPydanticモデルの**JSON Schema**はAPIの**OpenAPI**に含まれ、ドキュメントUIで使用されます。
|
||||
|
||||
FastAPI 0.99.0より前のバージョン(0.99.0以上は新しいOpenAPI 3.1.0を使用)では、他のユーティリティ(`Query()`、`Body()`など)で`example`または`examples`を使っても、それらの例はそのデータを説明するJSON Schema(OpenAPI独自版のJSON Schemaでさえ)には追加されず、OpenAPI内の*path operation*宣言に直接追加されていました(JSON Schemaを使用するOpenAPIの部分の外側)。
|
||||
|
||||
しかし、FastAPI 0.99.0以上ではOpenAPI 3.1.0を使用し、それはJSON Schema 2020-12とSwagger UI 5.0.0以上を使うため、すべてがより一貫し、例はJSON Schemaに含まれます。
|
||||
|
||||
### Swagger UIとOpenAPI固有の`examples` { #swagger-ui-and-openapi-specific-examples }
|
||||
|
||||
Swagger UIは複数のJSON Schema examplesをサポートしていなかった(2023-08-26時点)ため、ユーザーはドキュメントで複数の例を表示する手段がありませんでした。
|
||||
|
||||
それを解決するため、FastAPI `0.103.0`は、新しいパラメータ`openapi_examples`で、同じ古い**OpenAPI固有**の`examples`フィールドを宣言するための**サポートを追加**しました。🤓
|
||||
|
||||
### まとめ { #summary }
|
||||
|
||||
昔は歴史があまり好きではないと言っていました...が、今の私は「技術の歴史」の授業をしています。😅
|
||||
|
||||
要するに、**FastAPI 0.99.0以上にアップグレード**してください。そうすれば、物事はもっと**シンプルで一貫性があり直感的**になり、これらの歴史的詳細を知る必要もありません。😎
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# セキュリティ - 最初の一歩
|
||||
# セキュリティ - 最初の一歩 { #security-first-steps }
|
||||
|
||||
あるドメインに、**バックエンド** APIを持っているとしましょう。
|
||||
|
||||
@@ -12,25 +12,31 @@
|
||||
|
||||
**FastAPI**が提供するツールを使って、セキュリティを制御してみましょう。
|
||||
|
||||
## どう見えるか
|
||||
## どう見えるか { #how-it-looks }
|
||||
|
||||
まずはこのコードを使って、どう動くか観察します。その後で、何が起こっているのか理解しましょう。
|
||||
|
||||
## `main.py`を作成
|
||||
## `main.py`を作成 { #create-main-py }
|
||||
|
||||
`main.py`に、下記の例をコピーします:
|
||||
|
||||
{* ../../docs_src/security/tutorial001.py *}
|
||||
{* ../../docs_src/security/tutorial001_an_py39.py *}
|
||||
|
||||
## 実行
|
||||
## 実行 { #run-it }
|
||||
|
||||
/// info | 情報
|
||||
|
||||
まず<a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a>をインストールします。
|
||||
<a href="https://github.com/Kludex/python-multipart" class="external-link" target="_blank">`python-multipart`</a> パッケージは、`pip install "fastapi[standard]"` コマンドを実行すると **FastAPI** と一緒に自動的にインストールされます。
|
||||
|
||||
例えば、`pip install python-multipart`。
|
||||
しかし、`pip install fastapi` コマンドを使用する場合、`python-multipart` パッケージはデフォルトでは含まれません。
|
||||
|
||||
これは、**OAuth2**が `ユーザー名` や `パスワード` を送信するために、「フォームデータ」を使うからです。
|
||||
手動でインストールするには、[仮想環境](../../virtual-environments.md){.internal-link target=_blank}を作成して有効化し、次のコマンドでインストールしてください:
|
||||
|
||||
```console
|
||||
$ pip install python-multipart
|
||||
```
|
||||
|
||||
これは、**OAuth2**が `username` と `password` を送信するために、「フォームデータ」を使うからです。
|
||||
|
||||
///
|
||||
|
||||
@@ -39,14 +45,14 @@
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ uvicorn main:app --reload
|
||||
$ 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>
|
||||
|
||||
## 確認
|
||||
## 確認 { #check-it }
|
||||
|
||||
次のインタラクティブなドキュメントにアクセスしてください: <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>。
|
||||
|
||||
@@ -62,7 +68,7 @@ $ uvicorn main:app --reload
|
||||
|
||||
///
|
||||
|
||||
それをクリックすると、`ユーザー名`と`パスワード` (およびその他のオプションフィールド) を入力する小さな認証フォームが表示されます:
|
||||
それをクリックすると、`username` と `password`(およびその他のオプションフィールド)を入力する小さな認可フォームが表示されます:
|
||||
|
||||
<img src="/img/tutorial/security/image02.png">
|
||||
|
||||
@@ -80,11 +86,11 @@ $ uvicorn main:app --reload
|
||||
|
||||
また、同じアプリケーションのデバッグ、チェック、テストのためにも利用できます。
|
||||
|
||||
## `パスワード` フロー
|
||||
## `password` フロー { #the-password-flow }
|
||||
|
||||
では、少し話を戻して、どうなっているか理解しましょう。
|
||||
|
||||
`パスワード`の「フロー」は、OAuth2で定義されているセキュリティと認証を扱う方法 (「フロー」) の1つです。
|
||||
`password`の「フロー」は、OAuth2で定義されているセキュリティと認証を扱う方法 (「フロー」) の1つです。
|
||||
|
||||
OAuth2は、バックエンドやAPIがユーザーを認証するサーバーから独立したものとして設計されていました。
|
||||
|
||||
@@ -92,9 +98,9 @@ OAuth2は、バックエンドやAPIがユーザーを認証するサーバー
|
||||
|
||||
そこで、簡略化した箇所から見直してみましょう:
|
||||
|
||||
* ユーザーはフロントエンドで`ユーザー名`と`パスワード`を入力し、`Enter`を押します。
|
||||
* フロントエンド (ユーザーのブラウザで実行中) は、`ユーザー名`と`パスワード`をAPIの特定のURL (`tokenUrl="token"`で宣言された) に送信します。
|
||||
* APIは`ユーザー名`と`パスワード`をチェックし、「トークン」を返却します (まだ実装していません)。
|
||||
* ユーザーはフロントエンドで`username`と`password`を入力し、`Enter`を押します。
|
||||
* フロントエンド (ユーザーのブラウザで実行中) は、`username`と`password`をAPIの特定のURL (`tokenUrl="token"`で宣言された) に送信します。
|
||||
* APIは`username`と`password`をチェックし、「トークン」を返却します (まだ実装していません)。
|
||||
* 「トークン」はただの文字列であり、あとでこのユーザーを検証するために使用します。
|
||||
* 通常、トークンは時間が経つと期限切れになるように設定されています。
|
||||
* トークンが期限切れの場合は、再度ログインする必要があります。
|
||||
@@ -106,11 +112,11 @@ OAuth2は、バックエンドやAPIがユーザーを認証するサーバー
|
||||
* したがって、APIで認証するため、HTTPヘッダー`Authorization`に`Bearer`の文字列とトークンを加えた値を送信します。
|
||||
* トークンに`foobar`が含まれている場合、`Authorization`ヘッダーの内容は次のようになります: `Bearer foobar`。
|
||||
|
||||
## **FastAPI**の`OAuth2PasswordBearer`
|
||||
## **FastAPI**の`OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer }
|
||||
|
||||
**FastAPI**は、これらのセキュリティ機能を実装するために、抽象度の異なる複数のツールを提供しています。
|
||||
|
||||
この例では、**Bearer**トークンを使用して**OAuth2**を**パスワード**フローで使用します。これには`OAuth2PasswordBearer`クラスを使用します。
|
||||
この例では、**Bearer**トークンを使用して**OAuth2**を**Password**フローで使用します。これには`OAuth2PasswordBearer`クラスを使用します。
|
||||
|
||||
/// info | 情報
|
||||
|
||||
@@ -124,9 +130,9 @@ OAuth2は、バックエンドやAPIがユーザーを認証するサーバー
|
||||
|
||||
///
|
||||
|
||||
`OAuth2PasswordBearer` クラスのインスタンスを作成する時に、パラメーター`tokenUrl`を渡します。このパラメーターには、クライアント (ユーザーのブラウザで動作するフロントエンド) がトークンを取得するために`ユーザー名`と`パスワード`を送信するURLを指定します。
|
||||
`OAuth2PasswordBearer` クラスのインスタンスを作成する時に、パラメーター`tokenUrl`を渡します。このパラメーターには、クライアント (ユーザーのブラウザで動作するフロントエンド) がトークンを取得するために`username`と`password`を送信するURLを指定します。
|
||||
|
||||
{* ../../docs_src/security/tutorial001.py hl[6] *}
|
||||
{* ../../docs_src/security/tutorial001_an_py39.py hl[8] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
@@ -134,13 +140,13 @@ OAuth2は、バックエンドやAPIがユーザーを認証するサーバー
|
||||
|
||||
相対URLを使っているので、APIが`https://example.com/`にある場合、`https://example.com/token`を参照します。しかし、APIが`https://example.com/api/v1/`にある場合は`https://example.com/api/v1/token`を参照することになります。
|
||||
|
||||
相対 URL を使うことは、[プロキシと接続](../../advanced/behind-a-proxy.md){.internal-link target=_blank}のような高度なユースケースでもアプリケーションを動作させ続けるために重要です。
|
||||
相対 URL を使うことは、[プロキシの背後](../../advanced/behind-a-proxy.md){.internal-link target=_blank}のような高度なユースケースでもアプリケーションを動作させ続けるために重要です。
|
||||
|
||||
///
|
||||
|
||||
このパラメーターはエンドポイント/ *path operation*を作成しません。しかし、URL`/token`はクライアントがトークンを取得するために使用するものであると宣言します。この情報は OpenAPI やインタラクティブな API ドキュメントシステムで使われます。
|
||||
|
||||
実際のpath operationもすぐに作ります。
|
||||
実際の path operation もすぐに作ります。
|
||||
|
||||
/// info | 情報
|
||||
|
||||
@@ -160,13 +166,13 @@ oauth2_scheme(some, parameters)
|
||||
|
||||
そのため、`Depends`と一緒に使うことができます。
|
||||
|
||||
### 使い方
|
||||
### 使い方 { #use-it }
|
||||
|
||||
これで`oauth2_scheme`を`Depends`で依存関係に渡すことができます。
|
||||
|
||||
{* ../../docs_src/security/tutorial001.py hl[10] *}
|
||||
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
|
||||
|
||||
この依存関係は、*path operation function*のパラメーター`token`に代入される`str`を提供します。
|
||||
この依存関係は、*path operation 関数*のパラメーター`token`に代入される`str`を提供します。
|
||||
|
||||
**FastAPI**は、この依存関係を使用してOpenAPIスキーマ (および自動APIドキュメント) で「セキュリティスキーム」を定義できることを知っています。
|
||||
|
||||
@@ -178,13 +184,13 @@ OpenAPIと統合するセキュリティユーティリティ (および自動AP
|
||||
|
||||
///
|
||||
|
||||
## どのように動作するか
|
||||
## 何をするか { #what-it-does }
|
||||
|
||||
リクエストの中に`Authorization`ヘッダーを探しに行き、その値が`Bearer`と何らかのトークンを含んでいるかどうかをチェックし、そのトークンを`str`として返します。
|
||||
リクエストの中に`Authorization`ヘッダーを探しに行き、その値が`Bearer `と何らかのトークンを含んでいるかどうかをチェックし、そのトークンを`str`として返します。
|
||||
|
||||
もし`Authorization`ヘッダーが見つからなかったり、値が`Bearer`トークンを持っていなかったりすると、401 ステータスコードエラー (`UNAUTHORIZED`) で直接応答します。
|
||||
もし`Authorization`ヘッダーが見つからなかったり、値が`Bearer `トークンを持っていなかったりすると、401 ステータスコードエラー (`UNAUTHORIZED`) で直接応答します。
|
||||
|
||||
トークンが存在するかどうかをチェックしてエラーを返す必要はありません。関数が実行された場合、そのトークンに`str`が含まれているか確認できます。
|
||||
トークンが存在するかどうかをチェックしてエラーを返す必要はありません。関数が実行された場合、そのトークンに`str`が含まれていることを確信できます。
|
||||
|
||||
インタラクティブなドキュメントですでに試すことができます:
|
||||
|
||||
@@ -192,6 +198,6 @@ OpenAPIと統合するセキュリティユーティリティ (および自動AP
|
||||
|
||||
まだトークンの有効性を検証しているわけではありませんが、これはもう始まっています。
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
つまり、たった3~4行の追加で、すでに何らかの基礎的なセキュリティの形になっています。
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# 現在のユーザーの取得
|
||||
# 現在のユーザーの取得 { #get-current-user }
|
||||
|
||||
一つ前の章では、(依存性注入システムに基づいた)セキュリティシステムは、 *path operation関数* に `str` として `token` を与えていました:
|
||||
一つ前の章では、(依存性注入システムに基づいた)セキュリティシステムは、 *path operation 関数* に `str` として `token` を与えていました:
|
||||
|
||||
{* ../../docs_src/security/tutorial001.py hl[10] *}
|
||||
{* ../../docs_src/security/tutorial001_an_py39.py hl[12] *}
|
||||
|
||||
しかし、それはまだそんなに有用ではありません。
|
||||
|
||||
現在のユーザーを取得するようにしてみましょう。
|
||||
|
||||
## ユーザーモデルの作成
|
||||
## ユーザーモデルの作成 { #create-a-user-model }
|
||||
|
||||
まずは、Pydanticのユーザーモデルを作成しましょう。
|
||||
|
||||
ボディを宣言するのにPydanticを使用するのと同じやり方で、Pydanticを別のどんなところでも使うことができます:
|
||||
|
||||
{* ../../docs_src/security/tutorial002.py hl[5,12:16] *}
|
||||
{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *}
|
||||
|
||||
## 依存関係 `get_current_user` を作成
|
||||
## 依存関係 `get_current_user` を作成 { #create-a-get-current-user-dependency }
|
||||
|
||||
依存関係 `get_current_user` を作ってみましょう。
|
||||
|
||||
@@ -24,21 +24,21 @@
|
||||
|
||||
`get_current_user` は前に作成した `oauth2_scheme` と同じ依存関係を持ちます。
|
||||
|
||||
以前直接 *path operation* の中でしていたのと同じように、新しい依存関係である `get_current_user` は `str` として `token` を受け取るようになります:
|
||||
以前直接 *path operation* の中でしていたのと同じように、新しい依存関係である `get_current_user` はサブ依存関係である `oauth2_scheme` から `str` として `token` を受け取るようになります:
|
||||
|
||||
{* ../../docs_src/security/tutorial002.py hl[25] *}
|
||||
{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *}
|
||||
|
||||
## ユーザーの取得
|
||||
## ユーザーの取得 { #get-the-user }
|
||||
|
||||
`get_current_user` は作成した(偽物の)ユーティリティ関数を使って、 `str` としてトークンを受け取り、先ほどのPydanticの `User` モデルを返却します:
|
||||
|
||||
{* ../../docs_src/security/tutorial002.py hl[19:22,26:27] *}
|
||||
{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *}
|
||||
|
||||
## 現在のユーザーの注入
|
||||
## 現在のユーザーの注入 { #inject-the-current-user }
|
||||
|
||||
ですので、 `get_current_user` に対して同様に *path operation* の中で `Depends` を利用できます。
|
||||
|
||||
{* ../../docs_src/security/tutorial002.py hl[31] *}
|
||||
{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *}
|
||||
|
||||
Pydanticモデルの `User` として、 `current_user` の型を宣言することに注意してください。
|
||||
|
||||
@@ -54,15 +54,15 @@ Pydanticモデルの `User` として、 `current_user` の型を宣言するこ
|
||||
|
||||
/// check | 確認
|
||||
|
||||
依存関係システムがこのように設計されているおかげで、 `User` モデルを返却する別の依存関係(別の"dependables")を持つことができます。
|
||||
依存関係システムがこのように設計されているおかげで、 `User` モデルを返却する別の依存関係(別の「dependables」)を持つことができます。
|
||||
|
||||
同じデータ型を返却する依存関係は一つだけしか持てない、という制約が入ることはないのです。
|
||||
|
||||
///
|
||||
|
||||
## 別のモデル
|
||||
## 別のモデル { #other-models }
|
||||
|
||||
これで、*path operation関数* の中で現在のユーザーを直接取得し、`Depends` を使って、 **依存性注入** レベルでセキュリティメカニズムを処理できるようになりました。
|
||||
これで、*path operation 関数* の中で現在のユーザーを直接取得し、`Depends` を使って、 **依存性注入** レベルでセキュリティメカニズムを処理できるようになりました。
|
||||
|
||||
そして、セキュリティ要件のためにどんなモデルやデータでも利用することができます。(この場合は、 Pydanticモデルの `User`)
|
||||
|
||||
@@ -76,10 +76,9 @@ Pydanticモデルの `User` として、 `current_user` の型を宣言するこ
|
||||
|
||||
あなたのアプリケーションに必要なのがどんな種類のモデル、どんな種類のクラス、どんな種類のデータベースであったとしても、 **FastAPI** は依存性注入システムでカバーしてくれます。
|
||||
|
||||
## コードサイズ { #code-size }
|
||||
|
||||
## コードサイズ
|
||||
|
||||
この例は冗長に見えるかもしれません。セキュリティとデータモデルユーティリティ関数および *path operations* が同じファイルに混在しているということを覚えておいてください。
|
||||
この例は冗長に見えるかもしれません。セキュリティとデータモデルユーティリティ関数および *path operation* が同じファイルに混在しているということを覚えておいてください。
|
||||
|
||||
しかし、ここに重要なポイントがあります。
|
||||
|
||||
@@ -87,20 +86,20 @@ Pydanticモデルの `User` として、 `current_user` の型を宣言するこ
|
||||
|
||||
そして、それは好きなだけ複雑にすることができます。それでも、一箇所に、一度だけ書くのです。すべての柔軟性を備えます。
|
||||
|
||||
しかし、同じセキュリティシステムを使って何千ものエンドポイント(*path operations*)を持つことができます。
|
||||
しかし、同じセキュリティシステムを使って何千ものエンドポイント(*path operation*)を持つことができます。
|
||||
|
||||
そして、それらエンドポイントのすべて(必要な、どの部分でも)がこうした依存関係や、あなたが作成する別の依存関係を再利用する利点を享受できるのです。
|
||||
|
||||
さらに、こうした何千もの *path operations* は、たった3行で表現できるのです:
|
||||
さらに、こうした何千もの *path operation* は、たった3行で表現できるのです:
|
||||
|
||||
{* ../../docs_src/security/tutorial002.py hl[30:32] *}
|
||||
{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *}
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
これで、 *path operation関数* の中で直接現在のユーザーを取得できるようになりました。
|
||||
これで、 *path operation 関数* の中で直接現在のユーザーを取得できるようになりました。
|
||||
|
||||
既に半分のところまで来ています。
|
||||
|
||||
あとは、 `username` と `password` を実際にそのユーザーやクライアントに送る、 *path operation* を追加する必要があるだけです。
|
||||
あとは、ユーザー/クライアントが実際に `username` と `password` を送信するための *path operation* を追加する必要があるだけです。
|
||||
|
||||
次はそれを説明します。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# パスワード(およびハッシュ化)によるOAuth2、JWTトークンによるBearer
|
||||
# パスワード(およびハッシュ化)によるOAuth2、JWTトークンによるBearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens }
|
||||
|
||||
これでセキュリティの流れが全てわかったので、<abbr title="JSON Web Tokens">JWT</abbr>トークンと安全なパスワードのハッシュ化を使用して、実際にアプリケーションを安全にしてみましょう。
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
本章では、前章の続きから始めて、コードをアップデートしていきます。
|
||||
|
||||
## JWT について
|
||||
## JWT について { #about-jwt }
|
||||
|
||||
JWTとは「JSON Web Tokens」の略称です。
|
||||
|
||||
@@ -26,33 +26,31 @@ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4
|
||||
|
||||
JWT トークンを使って遊んでみたいという方は、<a href="https://jwt.io/" class="external-link" target="_blank">https://jwt.io</a> をチェックしてください。
|
||||
|
||||
## `python-jose` のインストール
|
||||
## `PyJWT` のインストール { #install-pyjwt }
|
||||
|
||||
PythonでJWTトークンの生成と検証を行うために、`python-jose`をインストールする必要があります:
|
||||
PythonでJWTトークンの生成と検証を行うために、`PyJWT`をインストールする必要があります。
|
||||
|
||||
[仮想環境](../../virtual-environments.md){.internal-link target=_blank}を作成し、アクティベートしてから、`pyjwt`をインストールしてください。
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install python-jose[cryptography]
|
||||
$ pip install pyjwt
|
||||
|
||||
---> 100%
|
||||
```
|
||||
|
||||
</div>
|
||||
|
||||
また、<a href="https://github.com/mpdavis/python-jose" class="external-link" target="_blank">Python-jose</a>だけではなく、暗号を扱うためのパッケージを追加で必要とします。
|
||||
/// info | 情報
|
||||
|
||||
ここでは、推奨されているものを使用します:<a href="https://cryptography.io/" class="external-link" target="_blank">pyca/cryptography</a>。
|
||||
RSAやECDSAのようなデジタル署名アルゴリズムを使用する予定がある場合は、cryptographyライブラリの依存関係`pyjwt[crypto]`をインストールしてください。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
このチュートリアルでは以前、<a href="https://pyjwt.readthedocs.io/" class="external-link" target="_blank">PyJWT</a>を使用していました。
|
||||
|
||||
しかし、Python-joseは、PyJWTのすべての機能に加えて、後に他のツールと統合して構築する際におそらく必要となる可能性のあるいくつかの追加機能を提供しています。そのため、代わりにPython-joseを使用するように更新されました。
|
||||
詳細は<a href="https://pyjwt.readthedocs.io/en/latest/installation.html" class="external-link" target="_blank">PyJWT Installation docs</a>で確認できます。
|
||||
|
||||
///
|
||||
|
||||
## パスワードのハッシュ化
|
||||
## パスワードのハッシュ化 { #password-hashing }
|
||||
|
||||
「ハッシュ化」とは、あるコンテンツ(ここではパスワード)を、規則性のないバイト列(単なる文字列)に変換することです。
|
||||
|
||||
@@ -60,26 +58,26 @@ $ pip install python-jose[cryptography]
|
||||
|
||||
しかし、規則性のないバイト列から元のパスワードに戻すことはできません。
|
||||
|
||||
### パスワードのハッシュ化を使う理由
|
||||
### パスワードのハッシュ化を使う理由 { #why-use-password-hashing }
|
||||
|
||||
データベースが盗まれても、ユーザーの平文のパスワードは盗まれず、ハッシュ値だけが盗まれます。
|
||||
|
||||
したがって、泥棒はそのパスワードを別のシステムで使えません(多くのユーザーはどこでも同じパスワードを使用しているため、危険性があります)。
|
||||
|
||||
## `passlib` のインストール
|
||||
## `pwdlib` のインストール { #install-pwdlib }
|
||||
|
||||
PassLib は、パスワードのハッシュを処理するための優れたPythonパッケージです。
|
||||
pwdlib は、パスワードのハッシュを処理するための優れたPythonパッケージです。
|
||||
|
||||
このパッケージは、多くの安全なハッシュアルゴリズムとユーティリティをサポートします。
|
||||
|
||||
推奨されるアルゴリズムは「Bcrypt」です。
|
||||
推奨されるアルゴリズムは「Argon2」です。
|
||||
|
||||
そのため、Bcryptを指定してPassLibをインストールします:
|
||||
[仮想環境](../../virtual-environments.md){.internal-link target=_blank}を作成し、アクティベートしてから、Argon2付きでpwdlibをインストールしてください。
|
||||
|
||||
<div class="termy">
|
||||
|
||||
```console
|
||||
$ pip install passlib[bcrypt]
|
||||
$ pip install "pwdlib[argon2]"
|
||||
|
||||
---> 100%
|
||||
```
|
||||
@@ -88,7 +86,7 @@ $ pip install passlib[bcrypt]
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
`passlib`を使用すると、**Django**や**Flask**のセキュリティプラグインなどで作成されたパスワードを読み取れるように設定できます。
|
||||
`pwdlib`を使用すると、**Django**や**Flask**のセキュリティプラグインなどで作成されたパスワードを読み取れるように設定できます。
|
||||
|
||||
例えば、Djangoアプリケーションからデータベース内の同じデータをFastAPIアプリケーションと共有できるだけではなく、同じデータベースを使用してDjangoアプリケーションを徐々に移行することもできます。
|
||||
|
||||
@@ -96,17 +94,17 @@ $ pip install passlib[bcrypt]
|
||||
|
||||
///
|
||||
|
||||
## パスワードのハッシュ化と検証
|
||||
## パスワードのハッシュ化と検証 { #hash-and-verify-the-passwords }
|
||||
|
||||
必要なツールを `passlib`からインポートします。
|
||||
必要なツールを `pwdlib`からインポートします。
|
||||
|
||||
PassLib の「context」を作成します。これは、パスワードのハッシュ化と検証に使用されるものです。
|
||||
推奨設定でPasswordHashインスタンスを作成します。これは、パスワードのハッシュ化と検証に使用されます。
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
PassLibのcontextには、検証だけが許された非推奨の古いハッシュアルゴリズムを含む、様々なハッシュアルゴリズムを使用した検証機能もあります。
|
||||
pwdlibはbcryptハッシュアルゴリズムもサポートしていますが、レガシーアルゴリズムは含みません。古いハッシュを扱うには、passlibライブラリを使用することが推奨されます。
|
||||
|
||||
例えば、この機能を使用して、別のシステム(Djangoなど)によって生成されたパスワードを読み取って検証し、Bcryptなどの別のアルゴリズムを使用して新しいパスワードをハッシュするといったことができます。
|
||||
例えば、この機能を使用して、別のシステム(Djangoなど)によって生成されたパスワードを読み取って検証し、Argon2やBcryptなどの別のアルゴリズムを使用して新しいパスワードをハッシュするといったことができます。
|
||||
|
||||
そして、同時にそれらはすべてに互換性があります。
|
||||
|
||||
@@ -118,15 +116,15 @@ PassLibのcontextには、検証だけが許された非推奨の古いハッシ
|
||||
|
||||
さらに、ユーザーを認証して返す関数も作成します。
|
||||
|
||||
{* ../../docs_src/security/tutorial004.py hl[7,48,55:56,59:60,69:75] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,56:57,60:61,70:76] *}
|
||||
|
||||
/// note | 備考
|
||||
|
||||
新しい(偽の)データベース`fake_users_db`を確認すると、ハッシュ化されたパスワードが次のようになっていることがわかります:`"$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW"`
|
||||
新しい(偽の)データベース`fake_users_db`を確認すると、ハッシュ化されたパスワードが次のようになっていることがわかります:`"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`。
|
||||
|
||||
///
|
||||
|
||||
## JWTトークンの取り扱い
|
||||
## JWTトークンの取り扱い { #handle-jwt-tokens }
|
||||
|
||||
インストールした複数のモジュールをインポートします。
|
||||
|
||||
@@ -148,33 +146,33 @@ $ openssl rand -hex 32
|
||||
|
||||
JWTトークンの署名に使用するアルゴリズム`"HS256"`を指定した変数`ALGORITHM`を作成します。
|
||||
|
||||
トークンの有効期限を指定した変数`ACCESS_TOKEN_EXPIRE_MINUTES`を作成します。
|
||||
トークンの有効期限を指定した変数を作成します。
|
||||
|
||||
レスポンスのトークンエンドポイントで使用するPydanticモデルを定義します。
|
||||
|
||||
新しいアクセストークンを生成するユーティリティ関数を作成します。
|
||||
|
||||
{* ../../docs_src/security/tutorial004.py hl[6,12:14,28:30,78:86] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,79:87] *}
|
||||
|
||||
## 依存関係の更新
|
||||
## 依存関係の更新 { #update-the-dependencies }
|
||||
|
||||
`get_current_user`を更新して、先ほどと同じトークンを受け取るようにしますが、今回はJWTトークンを使用します。
|
||||
|
||||
受け取ったトークンを復号して検証し、現在のユーザーを返します。
|
||||
受け取ったトークンをデコードして検証し、現在のユーザーを返します。
|
||||
|
||||
トークンが無効な場合は、すぐにHTTPエラーを返します。
|
||||
|
||||
{* ../../docs_src/security/tutorial004.py hl[89:106] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[90:107] *}
|
||||
|
||||
## `/token` パスオペレーションの更新
|
||||
## `/token` *path operation* の更新 { #update-the-token-path-operation }
|
||||
|
||||
トークンの有効期限を表す`timedelta`を作成します。
|
||||
|
||||
JWTアクセストークンを作成し、それを返します。
|
||||
実際のJWTアクセストークンを作成し、それを返します。
|
||||
|
||||
{* ../../docs_src/security/tutorial004.py hl[115:130] *}
|
||||
{* ../../docs_src/security/tutorial004_an_py310.py hl[118:133] *}
|
||||
|
||||
### JWTの"subject" `sub` についての技術的な詳細
|
||||
### JWTの「subject」`sub` についての技術的な詳細 { #technical-details-about-the-jwt-subject-sub }
|
||||
|
||||
JWTの仕様では、トークンのsubjectを表すキー`sub`があるとされています。
|
||||
|
||||
@@ -192,13 +190,13 @@ JWTは、ユーザーを識別して、そのユーザーがAPI上で直接操
|
||||
|
||||
しかしながら、それらのエンティティのいくつかが同じIDを持つ可能性があります。例えば、`foo`(ユーザー`foo`、車 `foo`、ブログ投稿`foo`)などです。
|
||||
|
||||
IDの衝突を回避するために、ユーザーのJWTトークンを作成するとき、subキーの値にプレフィックスを付けることができます(例えば、`username:`)。したがって、この例では、`sub`の値は次のようになっている可能性があります:`username:johndoe`
|
||||
IDの衝突を回避するために、ユーザーのJWTトークンを作成するとき、subキーの値にプレフィックスを付けることができます(例えば、`username:`)。したがって、この例では、`sub`の値は次のようになっている可能性があります:`username:johndoe`。
|
||||
|
||||
覚えておくべき重要なことは、`sub`キーはアプリケーション全体で一意の識別子を持ち、文字列である必要があるということです。
|
||||
|
||||
## 確認
|
||||
## 確認 { #check-it }
|
||||
|
||||
サーバーを実行し、ドキュメントに移動します:<a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>
|
||||
サーバーを実行し、ドキュメントに移動します:<a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>。
|
||||
|
||||
次のようなユーザーインターフェイスが表示されます:
|
||||
|
||||
@@ -232,17 +230,17 @@ Password: `secret`
|
||||
|
||||
<img src="/img/tutorial/security/image09.png">
|
||||
|
||||
開発者ツールを開くと、送信されるデータにはトークンだけが含まれており、パスワードはユーザーを認証してアクセストークンを取得する最初のリクエストでのみ送信され、その後は送信されないことがわかります。
|
||||
開発者ツールを開くと、送信されるデータにはトークンだけが含まれており、パスワードはユーザーを認証してアクセストークンを取得する最初のリクエストでのみ送信され、その後は送信されないことがわかります:
|
||||
|
||||
<img src="/img/tutorial/security/image10.png">
|
||||
|
||||
/// note | 備考
|
||||
|
||||
ヘッダーの`Authorization`には、`Bearer`で始まる値があります。
|
||||
ヘッダーの`Authorization`には、`Bearer `で始まる値があります。
|
||||
|
||||
///
|
||||
|
||||
## `scopes` を使った高度なユースケース
|
||||
## `scopes` を使った高度なユースケース { #advanced-usage-with-scopes }
|
||||
|
||||
OAuth2には、「スコープ」という概念があります。
|
||||
|
||||
@@ -252,7 +250,7 @@ OAuth2には、「スコープ」という概念があります。
|
||||
|
||||
これらの使用方法や**FastAPI**への統合方法については、**高度なユーザーガイド**で後ほど説明します。
|
||||
|
||||
## まとめ
|
||||
## まとめ { #recap }
|
||||
|
||||
ここまでの説明で、OAuth2やJWTなどの規格を使った安全な**FastAPI**アプリケーションを設定することができます。
|
||||
|
||||
@@ -266,7 +264,7 @@ OAuth2には、「スコープ」という概念があります。
|
||||
|
||||
そのため、プロジェクトに合わせて自由に選択することができます。
|
||||
|
||||
また、**FastAPI**は外部パッケージを統合するために複雑な仕組みを必要としないため、`passlib`や`python-jose`のようなよく整備され広く使われている多くのパッケージを直接使用することができます。
|
||||
また、**FastAPI**は外部パッケージを統合するために複雑な仕組みを必要としないため、`pwdlib`や`PyJWT`のようなよく整備され広く使われている多くのパッケージを直接使用することができます。
|
||||
|
||||
しかし、柔軟性、堅牢性、セキュリティを損なうことなく、可能な限りプロセスを簡素化するためのツールを提供します。
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# 静的ファイル
|
||||
# 静的ファイル { #static-files }
|
||||
|
||||
`StaticFiles` を使用して、ディレクトリから静的ファイルを自動的に提供できます。
|
||||
|
||||
## `StaticFiles` の使用
|
||||
## `StaticFiles` の使用 { #use-staticfiles }
|
||||
|
||||
* `StaticFiles` をインポート。
|
||||
* `StaticFiles()` インスタンスを生成し、特定のパスに「マウント」。
|
||||
* `StaticFiles()` インスタンスを特定のパスに「マウント」。
|
||||
|
||||
{* ../../docs_src/static_files/tutorial001.py hl[2,6] *}
|
||||
{* ../../docs_src/static_files/tutorial001_py39.py hl[2,6] *}
|
||||
|
||||
/// note | 技術詳細
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
|
||||
///
|
||||
|
||||
### 「マウント」とは
|
||||
### 「マウント」とは { #what-is-mounting }
|
||||
|
||||
「マウント」とは、特定のパスに完全な「独立した」アプリケーションを追加することを意味します。これにより、すべてのサブパスの処理がなされます。
|
||||
|
||||
これは、マウントされたアプリケーションが完全に独立しているため、`APIRouter` とは異なります。メインアプリケーションのOpenAPIとドキュメントには、マウントされたアプリケーションの内容などは含まれません。
|
||||
|
||||
これについて詳しくは、**高度なユーザーガイド** をご覧ください。
|
||||
これについて詳しくは、[高度なユーザーガイド](../advanced/index.md){.internal-link target=_blank} をご覧ください。
|
||||
|
||||
## 詳細
|
||||
## 詳細 { #details }
|
||||
|
||||
最初の `"/static"` は、この「サブアプリケーション」が「マウント」されるサブパスを指します。したがって、`"/static"` から始まるパスはすべてサブアプリケーションによって処理されます。
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
|
||||
`name="static"` は、**FastAPI** が内部で使用できる名前を付けます。
|
||||
|
||||
これらのパラメータはすべて「`静的`」とは異なる場合があり、独自のアプリケーションのニーズと詳細に合わせて調整します。
|
||||
これらのパラメータはすべて「`static`」とは異なる場合があり、独自のアプリケーションのニーズと詳細に合わせて調整します。
|
||||
|
||||
## より詳しい情報
|
||||
## より詳しい情報 { #more-info }
|
||||
|
||||
詳細とオプションについては、<a href="https://www.starlette.dev/staticfiles/" class="external-link" target="_blank">Starletteの静的ファイルに関するドキュメント</a>を確認してください。
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
# テスト
|
||||
# テスト { #testing }
|
||||
|
||||
<a href="https://www.starlette.dev/testclient/" class="external-link" target="_blank">Starlette</a> のおかげで、**FastAPI** アプリケーションのテストは簡単で楽しいものになっています。
|
||||
|
||||
<a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a> がベースなので、非常に使いやすく直感的です。
|
||||
<a href="https://www.python-httpx.org" class="external-link" target="_blank">HTTPX</a> がベースで、さらにその設計は Requests をベースにしているため、とても馴染みがあり直感的です。
|
||||
|
||||
これを使用すると、**FastAPI** と共に <a href="https://docs.pytest.org/" class="external-link" target="_blank">pytest</a> を直接利用できます。
|
||||
|
||||
## `TestClient` を使用
|
||||
## `TestClient` を使用 { #using-testclient }
|
||||
|
||||
/// info | 情報
|
||||
|
||||
`TestClient` を使用するには、まず <a href="https://www.python-httpx.org" class="external-link" target="_blank">`httpx`</a> をインストールします。
|
||||
|
||||
[仮想環境](../virtual-environments.md){.internal-link target=_blank} を作成し、それを有効化してから、例えば以下のようにインストールしてください:
|
||||
|
||||
```console
|
||||
$ pip install httpx
|
||||
```
|
||||
|
||||
///
|
||||
|
||||
`TestClient` をインポートします。
|
||||
|
||||
@@ -16,9 +28,9 @@
|
||||
|
||||
`httpx` と同じ様に `TestClient` オブジェクトを使用します。
|
||||
|
||||
チェックしたい Python の標準的な式と共に、シンプルに `assert` 文を記述します。
|
||||
チェックしたい Python の標準的な式と共に、シンプルに `assert` 文を記述します (これも `pytest` の標準です)。
|
||||
|
||||
{* ../../docs_src/app_testing/tutorial001.py hl[2,12,15:18] *}
|
||||
{* ../../docs_src/app_testing/tutorial001_py39.py hl[2,12,15:18] *}
|
||||
|
||||
/// tip | 豆知識
|
||||
|
||||
@@ -44,48 +56,81 @@ FastAPIアプリケーションへのリクエストの送信とは別に、テ
|
||||
|
||||
///
|
||||
|
||||
## テストの分離
|
||||
## テストの分離 { #separating-tests }
|
||||
|
||||
実際のアプリケーションでは、おそらくテストを別のファイルに保存します。
|
||||
|
||||
また、**FastAPI** アプリケーションは、複数のファイル/モジュールなどで構成されている場合もあります。
|
||||
|
||||
### **FastAPI** アプリファイル
|
||||
### **FastAPI** アプリファイル { #fastapi-app-file }
|
||||
|
||||
**FastAPI** アプリに `main.py` ファイルがあるとします:
|
||||
[Bigger Applications](bigger-applications.md){.internal-link target=_blank} で説明されている、次のようなファイル構成があるとします:
|
||||
|
||||
{* ../../docs_src/app_testing/main.py *}
|
||||
```
|
||||
.
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ └── main.py
|
||||
```
|
||||
|
||||
### テストファイル
|
||||
ファイル `main.py` に **FastAPI** アプリがあります:
|
||||
|
||||
次に、テストを含む `test_main.py` ファイルを作成し、`main` モジュール (`main.py`) から `app` をインポートします:
|
||||
|
||||
{* ../../docs_src/app_testing/test_main.py *}
|
||||
{* ../../docs_src/app_testing/app_a_py39/main.py *}
|
||||
|
||||
## テスト: 例の拡張
|
||||
### テストファイル { #testing-file }
|
||||
|
||||
次に、テストを含む `test_main.py` ファイルを用意できます。これは同じ Python パッケージ (`__init__.py` ファイルがある同じディレクトリ) に置けます:
|
||||
|
||||
``` hl_lines="5"
|
||||
.
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ └── test_main.py
|
||||
```
|
||||
|
||||
このファイルは同じパッケージ内にあるため、相対インポートを使って `main` モジュール (`main.py`) からオブジェクト `app` をインポートできます:
|
||||
|
||||
{* ../../docs_src/app_testing/app_a_py39/test_main.py hl[3] *}
|
||||
|
||||
|
||||
...そして、これまでと同じようにテストコードを書けます。
|
||||
|
||||
## テスト: 例の拡張 { #testing-extended-example }
|
||||
|
||||
次に、この例を拡張し、詳細を追加して、さまざまなパーツをテストする方法を確認しましょう。
|
||||
|
||||
### 拡張版 **FastAPI** アプリファイル { #extended-fastapi-app-file }
|
||||
|
||||
### 拡張版 **FastAPI** アプリファイル
|
||||
先ほどと同じファイル構成で続けます:
|
||||
|
||||
**FastAPI** アプリに `main_b.py` ファイルがあるとします。
|
||||
```
|
||||
.
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ └── test_main.py
|
||||
```
|
||||
|
||||
そのファイルには、エラーを返す可能性のある `GET` オペレーションがあります。
|
||||
ここで、**FastAPI** アプリがある `main.py` ファイルには、他の path operation があります。
|
||||
|
||||
また、いくつかのエラーを返す可能性のある `POST` オペレーションもあります。
|
||||
エラーを返す可能性のある `GET` オペレーションがあります。
|
||||
|
||||
これらの *path operation* には `X-Token` ヘッダーが必要です。
|
||||
いくつかのエラーを返す可能性のある `POST` オペレーションもあります。
|
||||
|
||||
{* ../../docs_src/app_testing/app_b_py310/main.py *}
|
||||
両方の *path operation* には `X-Token` ヘッダーが必要です。
|
||||
|
||||
### 拡張版テストファイル
|
||||
{* ../../docs_src/app_testing/app_b_an_py310/main.py *}
|
||||
|
||||
次に、先程のものに拡張版のテストを加えた、`test_main_b.py` を作成します。
|
||||
### 拡張版テストファイル { #extended-testing-file }
|
||||
|
||||
{* ../../docs_src/app_testing/app_b/test_main.py *}
|
||||
次に、拡張版のテストで `test_main.py` を更新できます:
|
||||
|
||||
リクエストに情報を渡せるクライアントが必要で、その方法がわからない場合はいつでも、`httpx` での実現方法を検索 (Google) できます。
|
||||
{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *}
|
||||
|
||||
|
||||
リクエストに情報を渡せるクライアントが必要で、その方法がわからない場合はいつでも、`httpx` での実現方法、あるいは HTTPX の設計が Requests の設計をベースにしているため `requests` での実現方法を検索 (Google) できます。
|
||||
|
||||
テストでも同じことを行います。
|
||||
|
||||
@@ -107,9 +152,11 @@ FastAPIアプリケーションへのリクエストの送信とは別に、テ
|
||||
|
||||
///
|
||||
|
||||
## 実行
|
||||
## 実行 { #run-it }
|
||||
|
||||
後は、`pytest` をインストールするだけです:
|
||||
その後、`pytest` をインストールするだけです。
|
||||
|
||||
[仮想環境](../virtual-environments.md){.internal-link target=_blank} を作成し、それを有効化してから、例えば以下のようにインストールしてください:
|
||||
|
||||
<div class="termy">
|
||||
|
||||
@@ -121,7 +168,7 @@ $ pip install pytest
|
||||
|
||||
</div>
|
||||
|
||||
ファイルを検知し、自動テストを実行し、結果のレポートを返します。
|
||||
ファイルとテストを自動的に検出し、実行して、結果のレポートを返します。
|
||||
|
||||
以下でテストを実行します:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user