FastAPI を使ってWEBアプリを作ってみる その1

2021-01-24Python,TIPSDocker,FastAPI

世の中はコロナウィルスの影響で色々と変わりましたね。
僕らのような職種はリモートワークと相性がいい事もあって在宅勤務に完全移行している方もかなり増えたのではないでしょうか。

普段はバックエンドでAPIサービスを構築する時、PythonだとDRFを使うことが多いのですが今回FastAPIを使用してみたところ大変素晴らしく感動したので在宅勤務で時間にゆとりも出ましたし、自身の備忘録も兼ね記事にしていこうと思います。

ドキュメントも充実していて、読みやすい。
これと一緒に公式が提示してるGitHub Repositoryを模写するだけでも余裕で覚えられると思う(汗

今回作るもの

たくさんのキュートなハリネズミの中からお気に入りの子を探し、来店時間を指定して会いに行くことができるサービスのバックエンドを作ってみます。
With コロナ時代の完全予約制ハリネズミカフェなんですかね、特に深い意図はないです。

折角なのでユーザ登録機能も用意し本格的な構成で臨んでみましょう。

セットアップ

Dockerを使用して開発していきましょう。
まずは今回作成していくアプリケーションの土台として次のようにディレクトリを構成します。

├── README.md
├── backend
│   ├── Dockerfile
│   ├── app
│   │   ├── api
│   │   └── core
│   ├── requirements.txt
│   └── tests
└── docker-compose.yml

今回の投稿ではFastAPIをコンテナで実行し簡単なAPIを試験的に動かすところまで実装します。

依存関係のインストール

スモールスタートしていきましょう、最低限必要なパッケージを requirements.txt に追加します。

fastapi==0.63.0
uvicorn==0.13.3
  • FastAPI 今回の主役。
  • uvicorn アプリを提供するために使用するASGIサーバー

server.py の作成

それでは早速コードを書いていきます。
最初はapi配下に server.py を作成します。

$ touch backend/app/api/__init__.py backend/app/api/server.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware


def get_application():
    app = FastAPI(title="Hedgehog Reservation", version="1.0.0")

    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

    return app

app = get_application()

ここでは CORSMiddleware を FastAPI から直接インポートしていますが、starlette をベースに構築されているだけあって from starlette.middleware.cors import CORSMiddleware とほぼ同義のようです。

Dockerfileの作成

さて、たった一つのファイルしかPythonを書いていませんが次はDockerfileを用意していきます。

FastAPI公式のドキュメントでも5行の1ファイルのみでHelloWorldしているのでDjangoと比べ導入もセットアップも非常にシンプルだと思います。

FROM python:3.9-alpine

WORKDIR /backend

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONBUFFERED 1

COPY ./requirements.txt /backend/requirements.txt

RUN set -eux \
 && apk add --no-cache build-base \
 && pip install --upgrade pip setuptools wheel \
 && pip install --no-cache-dir --trusted-host pypi.python.org -r /backend/requirements.txt \
 && apk del build-base \
 && rm -rf /root/.cache/pip

COPY . /backend

続いて、docker-compose.yml は次のように記述します。

version: '3.7'
services:
  server:
    build:
      context: ./backend
      dockerfile: Dockerfile
    volumes:
      - ./backend/:/backend/
    command: uvicorn app.api.server:app --reload --workers 1 --host 0.0.0.0 --port 8000
    ports:
      - 8000:8000

Dockerfileからイメージを作成し、コンテナを実行時に uvicorn で8000ポートにアプリケーションをホストさせます。
–reload フラグをつけることでAuto-Reloadに対応するため開発時はつけておくと良いでしょう。

ここまで出来たら一度コンテナを起動していきます。

$ docker-compose build
$ docker-compose up

コンテナが実行され、陽気なログが流れたことを確認できたらブラウザで localhost:8000 に移動します。

無事にサーバからJSONが返ってきました。
先ほど作成した server.py ではルートの設定をしていなかったため、次はルーティングしていきます。

ルートの設定

FastAPI の提供するルーティングシステムはとてもシンプルで簡単です。
ますはルート用のディレクトリを用意し、hedgehogs.py というルーティングファイルを作成します。

$ mkdir backend/app/api/routes
$ touch backend/app/api/routes/__init__.py backend/app/api/routes/hedgehogs.py

__init__.py ファイルも忘れずに作成してください。
続いてAPIルートにそれっぽい適当JSONを返すよう定義してみましょう。

from typing import List
from fastapi import APIRouter

router = APIRouter()

@router.get("/")
async def get_all_hedgehogs() -> List[dict]:
    hedgehogs = [
        {"id": 1, "name": "momo", "color": "SALT & PEPPER", "age": 2},
        {"id": 2, "name": "coco", "color": "DARK GREY", "age": 1.5}
    ]

    return hedgehogs

続いて __init__.py ファイルで親となるルータを定義し、hedgehogsに名前空間を割り当てます。

from fastapi import APIRouter
from app.api.routes.hedgehogs import router as hedgehogs_router


router = APIRouter()
router.include_router(hedgehogs_router, prefix="/hedgehogs", tags=["hedgehogs"])

最後に server.py に作成したルータを読み込ませます。

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.api.routes import router as api_router # 追加

def get_application():
    app = FastAPI(title="Hedgehog Reservation", version="1.0.0")

    app.add_middleware(
        CORSMiddleware,
        allow_origins=["*"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

    app.include_router(api_router, prefix="/api") # 追加

    return app

app = get_application()

これで準備完了です。
早速、定義した親ルータのprefix 'api’ に 子ルータのprefix 'hedgehogs’ を組み合わせてアクセスしてみましょう。

http://localhost:8000/api/hedgehogs/

それっぽいJSONが返ってきました!
めっちゃ簡単にAPIを作ることができました。 みんな大好きSwagger API Documentは http://localhost:8000/docs をひらけば確認できます。

まとめ

今回は久々の投稿だったのでリハビリ期間ということでこのあたりで終了です。
次回はPostgreSQLコンテナを構成に追加して、今回作成したFastAPIコンテナと接続をさせていきます。

作成したコードはGitHubにアップしています。
その1はpart1ブランチが対応しています。

2021-01-24Python,TIPSDocker,FastAPI

Posted by Kenny