Google ColaboratoryでFastAPIとDB（SQLModel）とStreamlitを連携する。

FaseAPIとStreamlitを使った簡単なWEBアプリをGoogle Colaboratory完結で作っていこうと思います。
せっかくなのでデータベースも使います（SQLModelで実装）。

# 動作
>GIF動画

![ezgif-5-fba0551651.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459843/bb505644-77d8-f6a4-dcb5-a45e10b205e1.gif)

WEBアプリと言っても、名簿を登録できるだけの単純なものです。

>フロー

ざっくりイメージはこんな感じです。
![Untitled Diagram.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459843/155b5e66-1fc7-31f0-9ebf-33e2f41155ba.jpeg)


`Streamlit`に接続
`/list`のレスポンスを表示
↓
フォームから名前と年齢を`/post`する
↓
受け取ったパラメータをDBに登録
↓
`/post`のレスポンスを表示
`/list`のレスポンスを表示

>フロント側　`Streamlit`

・名前と年齢を投稿するフォーム
・レスポンスを表示するエリア
・全件リストを表示するエリア
の３つのエリアで構成されています。

>API側　`FastAPI`

エンドポイントは`/post`と`/list`のみ
どちらもJSONを返します。
`/post`されたら`SQLModel`でDBに登録します。（簡単なバリデーションのみで、空白とかには対応してません。また、非同期ではありません。）
`/list`は全件を返します。


# ノートブック *＆* ソース
>[Google ColaboratoryでFastAPIとDB（SQLModel）とStreamlitを連携する。](https://colab.research.google.com/drive/1o-aGwGhm8pYPxzkUg-Qcy-N6Nz7EUsBg)

https://colab.research.google.com/drive/1o-aGwGhm8pYPxzkUg-Qcy-N6Nz7EUsBg

:::note info
<b>メニューバー①</b> > <b>ランタイム</b> > <b>すべてのセルを実行</b> で再現できるようにしています。
:::

![colab_screen.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459843/9c938da8-2a02-4403-7638-6c74083cd518.jpeg)

しばらくしたら下の方のコードセルの出力にて、`FastAPI`と`Streamlit`の起動を確認できます。
![スクリーンショット_2022-02-27_22-28-01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459843/2a296aec-1424-30e8-e6f1-186d57e4411f.jpeg)
`your url is: `にあるURLでStreamlitの画面に接続できます。
（loca.ltは繋がりにくい時間帯があるかもしれません）

>ディレクトリ構造

/content/colab_fastapi_streamlit
|--api
|　　|--main.py
|　　|--database.db
|　　|--run.py
|--front
|　　|--main.py
|　　|--run.py
|--docker
|　　|--Dockerfile
|　　|--requirements.txt
|--.env
|--Makefile
|--docker-compose.yml

簡略化のため極力１つのファイルにまとめるようにしました。
本来`api/main.py`はcontroller・スキーマ・router、DBなどを分けて管理した方がエンドポイントのパスが増えてきた場合に開発しやすいと思います。
近い内に分けたバージョンのノートブックも作ってみようと思います。

`Makefile`はいろんな実行処理をまとめるために置いています。
例えばターミナルにて$make runとかすると`api`や`front`のrun.pyをまとめて実行してくれます。
```shell
#$make help
init                 最初に行う処理です。ライブラリのインストールのみ。
backup               プロジェクトをzip化します。
run                  FastAPIとStreamlitを起動します。
docker-up            docker-composeでFastAPIとStreamlitを起動します。dockerを使う場合はこちらから。
help                 Display this help screen
```
ベタ打ちなら`Makefile`は無くてもかまいません。
docker使わないのであれば`docker`ディレクトリも`docker-compose.yml`も必要ありません。

# おまけ（Docker）
Dockerで再現できるようにしました（詳細は割愛します）。
最下コードセルの`プロジェクトのダウンロード`で今回のプロジェクトをダウンロードします。
解凍して`Makefile`ファイルのあるディレクトリでターミナルを起動して`$make docker-up`後、しばらくしたらコンテナが作成され`FastAPI`と`Streamlit`が起動するので`http://localhost:[Streamlitのポート番号]`でStreamlitに接続できます。
colabで立ち上げたアプリの続きから作業ができます。
コンテナやらを消して今回のプロジェクトに関わった環境をクリアに終了したい場合は、今回のプロジェクトの`docker-ocmpose.yml`のあるディレクトリ下で

```
$ docker-compose rm
$ docker-compose down --rmi local -v
```

これで綺麗サッパリ消えてくれます。


[Play With Docker](https://labs.play-with-docker.com/)にて動作確認できました。
（ただし、FastAPIのBASE_URLはPlay With Docker側のホストに変更しなければなりません。）

# おわりに
いかがでしたでしょうか。
フロント側をStreamlitで、APIサーバー側をFastAPIで、というようにそれぞれサーバーを立ち上げてお互い通信し合うようなアプリをcolab完結で作りました。メリットとしては単独でAPIを使うことができるのでフロント側は特定のGUIに囚われる事なく、スキーマ駆動開発ができることかなと思います。

# 参考

https://sqlmodel.tiangolo.com/features/

https://qiita.com/gudapys/items/62eda02bdb3de5530a23

https://qiita.com/gudapys/items/24a04b01438ea7e01678#%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%A8%E3%81%AE%E9%80%A3%E6%90%BA

https://zenn.dev/sh0nk/books/537bb028709ab9/viewer/86648d

https://qiita.com/po3rin/items/7875ef9db5ca994ff762