FastAPI のProject Generatorを試す


はじめに

前回ご紹介したFastAPIですが、どうやらボイラープレートが存在するようなので検証します。

環境

- ubuntu 20.04.2 LTS(wsl)
- python 3.8

インストール

ひな形作成前にopensslにてキーを作成する必要があるとの記載があったので作成しておきます。
出力値は後ほど使用するので控えておきましょう。

$ openssl rand -hex 32
2cfc~

以下コマンドでプロジェクトのひな形を作成します。
cookiecutterというツールを使用してgitのリポジトリからひな形を作成するみたいですね。

$ pip install cookiecutter
$ cookiecutter https://github.com/tiangolo/full-stack-fastapi-postgresql

ウィザード形式でプロジェクトに必要な情報を入力していきます。

project_name [Base Project]: abcApp
project_slug [abcapp]:
domain_main [abcapp.com]:
domain_staging [stag.abcapp.com]:
docker_swarm_stack_name_main [abcapp-com]:
docker_swarm_stack_name_staging [stag-abcapp-com]:
secret_key [changethis]: 2cfc~
first_superuser [[email protected]]:
first_superuser_password [changethis]: ●●●●●
backend_cors_origins [["http://localhost", "http://localhost:4200", "http://localhost:3000", "http://localhost:8080", "https://localhost", "https://localhost:4200", "https://localhost:3000", "https://localhost:8080", "http://dev.abcapp.com", "https://stag.abcapp.com", "https://abcapp.com", "http://local.dockertoolbox.tiangolo.com", "http://localhost.tiangolo.com"]]:
smtp_port [587]:
smtp_host []:
smtp_user []:
smtp_password []:
smtp_emails_from_email [[email protected]]:
postgres_password [changethis]: ●●●●●
pgadmin_default_user [[email protected]]:
pgadmin_default_user_password [admin]:
traefik_constraint_tag [abcapp.com]:
traefik_constraint_tag_staging [stag.abcapp.com]:
traefik_public_constraint_tag [traefik-public]:
flower_auth [admin:admin]:
sentry_dsn []:
docker_image_prefix []:
docker_image_backend [backend]:
docker_image_celeryworker [celeryworker]:
docker_image_frontend [frontend]:

とりあえずabcAppという名前でプロジェクトを作成しました。
いろいろな項目がありますね。
先ほど控えておいたkeyをsecret_keyとして設定しましょう。
フルスタックのプロジェクトテンプレート vue + fastAPI + postgres 
とうたっているためそれぞれがdockerコンテナとして起動する構成になっているらしいです。

作成されたファイルです。

├── README.md
├── backend
│   ├── app
│   │   ├── alembic
│   │   │   ├── README
│   │   │   ├── env.py
│   │   │   ├── script.py.mako
│   │   │   └── versions
│   │   │       └── d4867f3a4c0a_first_revision.py
│   │   ├── alembic.ini
│   │   ├── app
│   │   │   ├── __init__.py
│   │   │   ├── api
│   │   │   │   ├── __init__.py
│   │   │   │   ├── api_v1
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── api.py
│   │   │   │   │   └── endpoints
│   │   │   │   │       ├── __init__.py
│   │   │   │   │       ├── items.py
│   │   │   │   │       ├── login.py
│   │   │   │   │       ├── users.py
│   │   │   │   │       └── utils.py
│   │   │   │   └── deps.py
│   │   │   ├── backend_pre_start.py
│   │   │   ├── celeryworker_pre_start.py
│   │   │   ├── core
│   │   │   │   ├── __init__.py
│   │   │   │   ├── celery_app.py
│   │   │   │   ├── config.py
│   │   │   │   └── security.py
│   │   │   ├── crud
│   │   │   │   ├── __init__.py
│   │   │   │   ├── base.py
│   │   │   │   ├── crud_item.py
│   │   │   │   └── crud_user.py
│   │   │   ├── db
│   │   │   │   ├── __init__.py
│   │   │   │   ├── base.py
│   │   │   │   ├── base_class.py
│   │   │   │   ├── init_db.py
│   │   │   │   └── session.py
│   │   │   ├── email-templates
│   │   │   │   ├── build
│   │   │   │   │   ├── new_account.html
│   │   │   │   │   ├── reset_password.html
│   │   │   │   │   └── test_email.html
│   │   │   │   └── src
│   │   │   │       ├── new_account.mjml
│   │   │   │       ├── reset_password.mjml
│   │   │   │       └── test_email.mjml
│   │   │   ├── initial_data.py
│   │   │   ├── main.py
│   │   │   ├── models
│   │   │   │   ├── __init__.py
│   │   │   │   ├── item.py
│   │   │   │   └── user.py
│   │   │   ├── schemas
│   │   │   │   ├── __init__.py
│   │   │   │   ├── item.py
│   │   │   │   ├── msg.py
│   │   │   │   ├── token.py
│   │   │   │   └── user.py
│   │   │   ├── tests
│   │   │   │   ├── __init__.py
│   │   │   │   ├── api
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   └── api_v1
│   │   │   │   │       ├── __init__.py
│   │   │   │   │       ├── test_celery.py
│   │   │   │   │       ├── test_items.py
│   │   │   │   │       ├── test_login.py
│   │   │   │   │       └── test_users.py
│   │   │   │   ├── conftest.py
│   │   │   │   ├── crud
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── test_item.py
│   │   │   │   │   └── test_user.py
│   │   │   │   └── utils
│   │   │   │       ├── __init__.py
│   │   │   │       ├── item.py
│   │   │   │       ├── user.py
│   │   │   │       └── utils.py
│   │   │   ├── tests_pre_start.py
│   │   │   ├── utils.py
│   │   │   └── worker.py
│   │   ├── mypy.ini
│   │   ├── prestart.sh
│   │   ├── pyproject.toml
│   │   ├── scripts
│   │   │   ├── format-imports.sh
│   │   │   ├── format.sh
│   │   │   ├── lint.sh
│   │   │   ├── test-cov-html.sh
│   │   │   └── test.sh
│   │   ├── tests-start.sh
│   │   └── worker-start.sh
│   ├── backend.dockerfile
│   └── celeryworker.dockerfile
├── cookiecutter-config-file.yml
├── docker-compose.override.yml
├── docker-compose.yml
├── frontend
│   ├── Dockerfile
│   ├── README.md
│   ├── babel.config.js
│   ├── nginx-backend-not-found.conf
│   ├── package.json
│   ├── public
│   │   ├── favicon.ico
│   │   ├── img
│   │   │   └── icons
│   │   │       ├── android-chrome-192x192.png
│   │   │       ├── android-chrome-512x512.png
│   │   │       ├── apple-touch-icon-120x120.png
│   │   │       ├── apple-touch-icon-152x152.png
│   │   │       ├── apple-touch-icon-180x180.png
│   │   │       ├── apple-touch-icon-60x60.png
│   │   │       ├── apple-touch-icon-76x76.png
│   │   │       ├── apple-touch-icon.png
│   │   │       ├── favicon-16x16.png
│   │   │       ├── favicon-32x32.png
│   │   │       ├── msapplication-icon-144x144.png
│   │   │       ├── mstile-150x150.png
│   │   │       └── safari-pinned-tab.svg
│   │   ├── index.html
│   │   ├── manifest.json
│   │   └── robots.txt
│   ├── src
│   │   ├── App.vue
│   │   ├── api.ts
│   │   ├── assets
│   │   │   └── logo.png
│   │   ├── component-hooks.ts
│   │   ├── components
│   │   │   ├── NotificationsManager.vue
│   │   │   ├── RouterComponent.vue
│   │   │   └── UploadButton.vue
│   │   ├── env.ts
│   │   ├── interfaces
│   │   │   └── index.ts
│   │   ├── main.ts
│   │   ├── plugins
│   │   │   ├── vee-validate.ts
│   │   │   └── vuetify.ts
│   │   ├── registerServiceWorker.ts
│   │   ├── router.ts
│   │   ├── shims-tsx.d.ts
│   │   ├── shims-vue.d.ts
│   │   ├── store
│   │   │   ├── admin
│   │   │   │   ├── actions.ts
│   │   │   │   ├── getters.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── mutations.ts
│   │   │   │   └── state.ts
│   │   │   ├── index.ts
│   │   │   ├── main
│   │   │   │   ├── actions.ts
│   │   │   │   ├── getters.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── mutations.ts
│   │   │   │   └── state.ts
│   │   │   └── state.ts
│   │   ├── utils.ts
│   │   └── views
│   │       ├── Login.vue
│   │       ├── PasswordRecovery.vue
│   │       ├── ResetPassword.vue
│   │       └── main
│   │           ├── Dashboard.vue
│   │           ├── Main.vue
│   │           ├── Start.vue
│   │           ├── admin
│   │           │   ├── Admin.vue
│   │           │   ├── AdminUsers.vue
│   │           │   ├── CreateUser.vue
│   │           │   └── EditUser.vue
│   │           └── profile
│   │               ├── UserProfile.vue
│   │               ├── UserProfileEdit.vue
│   │               └── UserProfileEditPassword.vue
│   ├── tests
│   │   └── unit
│   │       └── upload-button.spec.ts
│   ├── tsconfig.json
│   ├── tslint.json
│   └── vue.config.js
└── scripts
    ├── build-push.sh
    ├── build.sh
    ├── deploy.sh
    ├── test-local.sh
    └── test.sh

どうやらユーザーのCRUD機能と認証機能がデフォルトで実装されていて、そこから各機能を拡張するような感じですね。

コンテナの起動

コンテナを起動してみます。

$ cd abcapp
$ docker-compose up -d

結構な時間がかかりましたがコンテナが立ち上がりました。

localhost:80/にアクセスしてみます。

先ほど入力したadminのID/Passでログインしてみます。

ユーザーの登録画面が開きました。
UIセットはvuetifyを使用しているようですね。

若干重厚長大なテンプレートな感じはしますが(見たらpgAdminのコンテナまでありました。)、コンテナやDB周りの設定などある程度の基礎が出来上がっているうえで参考になるコードも見られるというのはとてもいいと思います。不要なコンテナ等は削っていけばいいですしね。
私のような初心者はこのコードをまずは見ながら実際ものを作っていくほうが習得の近道かもしれません。