このセクションの内容を補完するために脱初心者用コースを受けたい場合は、**TestDriven.io**による、<ahref="https://testdriven.io/courses/tdd-fastapi/"class="external-link"target="_blank">Test-Driven Development with FastAPI and Docker</a>を確認するのがよいかもしれません。
この例では、Pydanticモデルを一切宣言していません。実際、リクエストボディはJSONとして <abbrtitle="converted from some plain format, like bytes, into Python objects – bytesなどのプレーンな形式からPythonオブジェクトに変換すること">parsed</abbr> されず、直接 `bytes` として読み取られます。そして `magic_data_reader()` 関数が、何らかの方法でそれをパースする責務を担います。
それでも、リクエストボディに期待されるスキーマを宣言できます。
### カスタムOpenAPI content type { #custom-openapi-content-type }
これは `docker compose` を使用する場合にかなり目立つことがあります。より技術的な詳細は、このDocker ComposeのFAQセクションをご覧ください:<ahref="https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop"class="external-link"target="_blank">Why do my services take 10 seconds to recreate or stop?</a>。
**Kubernetes** や Docker Swarm モード、Nomad、あるいは複数のマシン上で分散コンテナを管理するための同様の複雑なシステムを使ってマシンの<abbrtitle="A group of machines that are configured to be connected and work together in some way. - ある方法で接続され、連携して動作するように構成されたマシンの集まり">cluster</abbr>を構成している場合、 各コンテナで(Workerを持つUvicornのような)**プロセスマネージャ**を使用する代わりに、**クラスター・レベル**で**レプリケーション**を処理したいと思うでしょう。
このイメージは、主に上記で説明した状況で役に立つでしょう: [複数のプロセスと特殊なケースを持つコンテナ(Containers with Multiple Processes and Special Cases)](#containers-with-multiple-processes-and-special-cases)
このベースイメージや類似のイメージは**必要ない**可能性が高いので、[上記の: FastAPI用のDockerイメージをビルドする(Build a Docker Image for FastAPI)](#build-a-docker-image-for-fastapi)のようにゼロからイメージをビルドする方が良いでしょう。
そのような場合は、上記のように**ゼロから**イメージを構築する方がよいでしょう: [FastAPI用のDockerイメージをビルドする(Build a Docker Image for FastAPI)](#build-a-docker-image-for-fastapi) を参照してください。
このイメージは、主に上記の[複数のプロセスと特殊なケースを持つコンテナ(Containers with Multiple Processes and Special Cases)](#containers-with-multiple-processes-and-special-cases)で説明したような特殊なケースで役に立ちます。
* **TLS**プロトコル(HTTPの前に、TCPレベルで暗号化を処理するもの)には、**<ahref="https://en.wikipedia.org/wiki/Server_Name_Indication"class="external-link"target="_blank"><abbrtitle="Server Name Indication">SNI</abbr></a>**と呼ばれる**拡張**があります。
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> server </font></span> Server started at <fontcolor="#729FCF"><ustyle="text-decoration-style:solid">http://0.0.0.0:8000</u></font>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> server </font></span> Documentation at <fontcolor="#729FCF"><ustyle="text-decoration-style:solid">http://0.0.0.0:8000/docs</u></font>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Uvicorn running on <fontcolor="#729FCF"><ustyle="text-decoration-style:solid">http://0.0.0.0:8000</u></font><b>(</b>Press CTRL+C to
quit<b>)</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started parent process <b>[</b><fontcolor="#34E2E2"><b>27365</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>27368</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>27369</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>27370</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>27367</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
環境変数についての詳細は、<ahref="https://en.wikipedia.org/wiki/Environment_variable"class="external-link"target="_blank">Wikipedia for Environment Variable</a>も参照してください。
もし Web API の代わりにターミナルで使用する<abbrtitle="Command Line Interface">CLI</abbr>アプリを構築する場合は、<ahref="https://typer.tiangolo.com/"class="external-link"target="_blank">**Typer**</a>を確認してください。
<ahref="https://www.youtube.com/watch?v=mpR8ngthqiE"target="_blank"><imgsrc="https://fastapi.tiangolo.com/img/fastapi-documentary.jpg"alt="FastAPI Mini Documentary"></a>
- Web の部分は<ahref="https://www.starlette.dev/"class="external-link"target="_blank">Starlette</a>
Web API の代わりにターミナルで使用する <abbrtitle="Command Line Interface">CLI</abbr> アプリを構築する場合は、<ahref="https://typer.tiangolo.com/"class="external-link"target="_blank">**Typer**</a> を確認してください。
- <ahref="https://github.com/Kludex/python-multipart"target="_blank"><code>python-multipart</code></a> - <abbrtitle="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>`request.form()`からの変換をサポートしたい場合は必要です。
* <ahref="https://github.com/Kludex/python-multipart"target="_blank"><code>python-multipart</code></a> - `request.form()` とともに、フォームの <abbrtitle="converting the string that comes from an HTTP request into Python data">「parsing」</abbr> をサポートしたい場合に必要です。
Python 3.10では、受け付ける可能性のある型を<abbrtitle='also called "bitwise or operator", but that meaning is not relevant here'>縦棒(`|`)</abbr>で区切って書ける **新しい構文** もあります。
Python 3.10では、ジェネリクスの`Union`や`Optional`を使う代替として、型のユニオンを宣言するために<abbrtitle='also called "bitwise or operator", but that meaning is not relevant here'>縦棒(`|`)</abbr>を使えます。これはずっと良く、よりシンプルです。
Pythonには、`Annotated`を使って型ヒントに**追加の<abbrtitle="Data about the data, in this case, information about the type, e.g. a description.">メタデータ</abbr>**を付与できる機能もあります。
そして、返された値を<abbrtitle="A utility/system to store computed/generated values, to reuse them instead of computing them again. – 計算/生成された値を保存し、再計算する代わりに再利用するためのユーティリティ/システム。">「キャッシュ」</abbr>に保存し、同じリクエストに対して依存関係を何度も呼び出す代わりに、その特定のリクエストでそれを必要とする全ての「依存」に渡すことになります。
* Pydanticでは「ISO 8601 time diff encoding」として表現することも可能です。<ahref="https://docs.pydantic.dev/latest/concepts/serialization/"class="external-link"target="_blank">詳細はドキュメントを参照してください</a>。
* Pydanticでは「ISO 8601 time diff encoding」として表現することも可能です。<ahref="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の全ての有効な型はこちらで確認できます: <ahref="https://docs.pydantic.dev/latest/usage/types/types/"class="external-link"target="_blank">Pydantic data types</a>。
* Pydanticの全ての有効な型はこちらで確認できます: <ahref="https://docs.pydantic.dev/latest/concepts/types/"class="external-link"target="_blank">Pydantic data types</a>。
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> app </font></span> Using import string: <fontcolor="#3465A4">main:app</font>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> server </font></span> Server started at <fontcolor="#729FCF"><ustyle="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> server </font></span> Documentation at <fontcolor="#729FCF"><ustyle="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> tip </font></span> Running in development mode, for production use:
<b>fastapi run</b>
Logs:
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Will watch for changes in these directories:
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Uvicorn running on <fontcolor="#729FCF"><ustyle="text-decoration-style:solid">http://127.0.0.1:8000</u></font><b>(</b>Press CTRL+C
to quit<b>)</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><fontcolor="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>383153</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
```
</div>
出力には次のような行があります:
@ -40,7 +56,7 @@ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> app </font></span> Using import string: <fontcolor="#3465A4">main:app</font>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> server </font></span> Server started at <fontcolor="#729FCF"><ustyle="text-decoration-style:solid">http://127.0.0.1:8000</u></font>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> server </font></span> Documentation at <fontcolor="#729FCF"><ustyle="text-decoration-style:solid">http://127.0.0.1:8000/docs</u></font>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> tip </font></span> Running in development mode, for production use:
<b>fastapi run</b>
<spanstyle="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
<spanstyle="color: green;">INFO</span>: Started reloader process [28720]
<spanstyle="color: green;">INFO</span>: Started server process [28722]
<spanstyle="color: green;">INFO</span>: Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Uvicorn running on <fontcolor="#729FCF"><ustyle="text-decoration-style:solid">http://127.0.0.1:8000</u></font><b>(</b>Press CTRL+C
to quit<b>)</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started reloader process <b>[</b><fontcolor="#34E2E2"><b>383138</b></font><b>]</b> using WatchFiles
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Started server process <b>[</b><fontcolor="#34E2E2"><b>383153</b></font><b>]</b>
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Waiting for application startup.
<spanstyle="background-color:#007166"><fontcolor="#D3D7CF"> INFO </font></span> Application startup complete.
説明文は長くて複数行におよぶ傾向があるので、関数<abbrtitle="a multi-line string as the first expression inside a function (not assigned to any variable) used for documentation – ドキュメントに使用される関数内の最初の式(変数に代入されていない)としての複数行の文字列">docstring</abbr>内に*path operation*の説明文を宣言できます。すると、**FastAPI** は説明文を読み込んでくれます。
ここで重要になってくるのは<abbrtitle="greater than – より大きい"><code>gt</code></abbr>だけでなく<abbrtitle="greater than or equal – 以上"><code>ge</code></abbr>も宣言できることです。これと同様に、例えば、値が`1`より小さくても`0`より大きくなければならないことを要求することができます。
したがって、`0.5`は有効な値ですが、`0.0`や`0`はそうではありません。
これは<abbrtitle="未満"><code>lt</code></abbr>も同じです。
これは<abbrtitle="less than – より小さい"><code>lt</code></abbr>も同じです。
パラメータが一致するべき<abbrtitle="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings.">正規表現</abbr>`pattern`を定義することができます:
例えば、このカスタムバリデータは、<abbrtitle="ISBN means International Standard Book Number – 国際標準図書番号">ISBN</abbr> の書籍番号なら item ID が `isbn-` で始まること、<abbrtitle="IMDB (Internet Movie Database) is a website with information about movies – IMDB(Internet Movie Database)は映画に関する情報を掲載するWebサイトです">IMDB</abbr> の movie URL ID なら `imdb-` で始まることをチェックします:
それぞれのステータスコードとどのコードが何のためのコードなのかについて詳細は<ahref="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"class="external-link"target="_blank"><abbrtitle="Mozilla Developer Network">MDN</abbr>documentation about HTTP status codes</a>を参照してください。
* <ahref="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の以下で使用されました:
Pythonプロジェクトでの**初めての**作業を開始する際には、**<abbrtitle="there are other options, this is a simple guideline – 他の選択肢もありますが、これはシンプルなガイドラインです">プロジェクト内</abbr>**に仮想環境を作成してください。
こうすることで、そのパッケージがインストールした**ターミナル(<abbrtitle="command line interface">CLI</abbr>)プログラム**を使用する場合に、仮想環境内のものが確実に使われ、グローバル環境にインストールされている別のもの(おそらく必要なものとは異なるバージョン)を誤って使用することを防ぎます。