FastAPIで作るWebアプリ - 基本

PythonでAsyncioを使った非同期的プログラミングを追求してきた結果、FastAPIにぶつかりました。Python界においてはモダンなWeb Frameworkということで人気のようです。少し調査していきたいと思います。


【過去記事】
[Python Asyncio入門](https://qiita.com/sand/items/0e445a13d81d20ea33c3)
[Aiohttpで作るSimple Web Server - Qiita](https://qiita.com/sand/items/971c851598ff59c1c905)
[Starletteで作る Simple Web Server - QIita](https://qiita.com/sand/items/dd622ce4f9249399974c)
[FastAPIで作るWebアプリ - 基本](https://qiita.com/sand/items/bba0913fe4504c612b3a)
[FastAPIで作るWebアプリ - validation](https://qiita.com/sand/items/85068532388826258df4)
[FastAPIで作るWebアプリ - Body validation](https://qiita.com/sand/items/470b33d7539713432090)
[FastAPIで作るWebアプリ - Form validation](https://qiita.com/sand/items/207f306bdacdc0fb9571)

[FastAPI 公式サイト](https://fastapi.tiangolo.com/ja/)

以下の情報は公式サイトのチュートリアルの最初のステップを短くまとめたものです。


# 1.ハローワールド

インストールは以下のコマンドだけで行えます。

```
pip install fastapi[all]
```

簡単なハローワールドプログラムを示します。


```python:main.py
from fastapi import FastAPI

app = FastAPI() # FastAPIはStarletteを直接継承するクラスです。


@app.get("/")  # デコレーション、パス= /, オペレーション = get
async def root():
    return {"message": "Hello World"} # コンテンツの生成
```


FastAPIはStarletteを直接継承するクラスです。**FastAPIでもStarletteのすべての機能を利用可能です。**
[「Starletteで作る Simple Web Server」](https://qiita.com/sand/items/dd622ce4f9249399974c)


以下のコマンドでアプリを起動できます。

```
uvicorn main:app --reload
```

以下は起動コマンドの説明

* main: main.pyファイル (Python "module")。
* app: main.py内部で作られるobject（app = FastAPI()のように記述される）。
* --reload: コードの変更時にサーバーを再起動させる。開発用。


起動メッセージです

```
$uvicorn main:app --reload
INFO:     Will watch for changes in these directories: ['C:\\Users\\User\\git\\python\\asyncio\\fastapi']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [12544] using watchgod
INFO:     Started server process [12916]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
```

メッセージに従って、ブラウザで http://localhost:8000 にアクセスすると以下のコンテンツを受け取ります。

```
{"message": "Hello World"}
```


## 対話的APIドキュメント
これまでの操作だけで、以下のようなドキュメントが自動生成されます。**Swagger UI**で実装されており、RESTful APIの仕様書であり、実際に**Requestを発行することができます。**開発効率に大きく寄与するものです。
http://localhost:8000/docs


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/eefebbaa-f479-d15a-398e-a71f50562b90.png)

「Try it out」ボタンをクリックすると、以下のように「Execute」ボタンが現れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/7bb05038-f344-9ec7-6db9-892276decaa9.png)


この場合はパラメータは無いので、そのまま「Execute」ボタンをクリックするとリクエストが発行されます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/1f93efde-3408-27f6-ee5d-636e43ea1384.png)


発行されたRequestと結果のResponseが表示されます。とても便利です。次にパラメータを持つRequestについて見たいと思います。



# 2.パラメータ

つぎにパスパラメータ、クエリパラメータ、リクエストボディの受け取り方と、Swagger UIを使った確認方法を見ていきましょう。

```python:param.py
from fastapi import FastAPI

app = FastAPI()

###############################
### パスパラメータ
###############################
@app.get("/items/{item_id}")
async def read_item(item_id : int):
    return {"item_id": item_id}


###############################
### クエリパラメータ
###############################
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]

@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return fake_items_db[skip : skip + limit]



###############################
### リクエストボディ
###############################
from typing import Optional
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None

@app.post("/items/")
async def create_item(item: Item):
    return item
```

リクエストボディの場合について補足です。
* pydantic から BaseModel をインポートします。
* BaseModel を継承したクラスとしてデータモデル(Class Item)を宣言します


Swagger UIは以下のように表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/4162aa41-fbb0-70a4-501d-56fd9698a37c.png)


## 2-1 パスパラメータ

最初のGETを選択します。まだパラメータの入力はできません。「Try it out」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/fadc7441-7279-092d-d107-f5d4f532461f.png)

**この状態で初めてパラメータを入力できます**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/85061cfe-66e9-5e6b-9e59-8b85ffc69134.png)


パラメータを入力したら、[Execute]ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/af7fdb37-3323-597d-42e5-96cb3605c822.png)


発行されたRequestと成功のResponseが表示されます。

それではパラメータに整数ではなく「Foo」という文字列を入力したらどうでしょう？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/4d766a4b-cd52-adb8-add1-72ff03afde59.png)

どうやらSwagger UIレベルでエラーになり、Requestは発行されないようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/63de89be-6623-ae51-39ed-a9f0ded82724.png)



## 2-2. クエリパラメータ
2番目のGETを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/9bfbcbb4-ece5-5e3e-173b-13d544e5d65d.png)


パラメータにskip=1, limit=30 を指定します。「Execute」ボタンをクリックします。以下の結果が得られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/fa463806-9815-fa11-c7a5-cc4ed19de948.png)



## 2-3. リクエストボディ

POSTを選びます。リクエストボディを入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/cedbf777-d4cc-24f8-64e2-5955472bd15d.png)

「Execute」ボタンをクリックすると、以下のような結果が得られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/63826acb-e698-a5cf-40cd-63041053c651.png)


Restful APIの開発と確認が非常に簡単に行えることがわかります。

今回は以上です