FastAPI環境構築

前回の投稿にてDjangoの置き替えとしてFastAPIの勉強を始めてかなり時間が経ってしまいましたが、まずはDjangoの時と同じようにシングルページWEBアプリケーションのテンプレートのような形で勉強しようと思い、同様にDockerの環境構築からの覚え書きです。

  • PythonイメージベースのDockerfile
    • nodejsをインストールして、モジュールとしてTypescript、Bootstrap、SASSを追加
    • Pythonライブラリとしてfastapi関連ライブラリをインストール
    • 実行ユーザーappを作成してsudo権限を与える
  • nginxプロキシを追加したdocker-compose.yml
    • /codeをマウントしてここにアプリを配置する
    • startupスクリプトを実行させる(環境変数設定とtypescript、sassコンパイラの常駐設定、APIサーバー:uvicornのデーモン起動)

上記プロジェクトを用いてdocker-compose up -dすると、サーバーが起動してブラウザからhttp://localhost:8080/でアクセス出来るようになります。

WEBアプリケーションの実体はapp/main.pyです。サンプルではある程度サンプルページが表示されるまで作り込んでしまっていますが、覚え書きとして一番単純なアプリケーションから

from fastapi import FastAPI

app = FastAPI()

@app.get('/')
async def index():
    return {'detail': 'Hello FastAPI World.'}

として、保存。ブラウザからhttp://localhost:8080/で読み込むと、

一番単純なFastAPIアプリ

こんな感じで表示されます。

app/main.pyの1行目でライブラリを読み込んで、アプリケーションインタンスの生成(3行目)、5行目はHTTPリクエストメソッドを表す関数デコレータです。例ではルートパスに対するGETリクエスト。その下のdefが関数定義で、名前は分かりやすければ何でも良いです。この関数の戻り値がHTTPのレスポンスとしてブラウザに返されます。

見て分かるように、このアプリケーションで返されるレスポンスはHTMLではないため、結果の見た目が変です。

FastAPIはDjangoと異なりAPIが主体なのでデフォルトではJSONで返すのが基本のようです。Ajaxなどでデータのやりとりをするのに向いている感じ。

HTTP通信を使用したアプリケーションでデータのやりとりを行い、クライアント側で見た目を準備するような用途ではこのままで良さそうですが、普通のWEBアプリのようにブラウザから利用したい場合はひと工夫が必要です。

少し調べた感じでは、二通りの方法があるようです。

  1. Jinja2Templatesテンプレートライブラリを利用する
    • FastAPIのもととなるStarletteやFlaskでも使用されており、Djangoのテンプレートと同様に変数埋込で動的なHTML文書を返すことが出来る。
  2. スタティックマウントしたディレクトリでhtmlを有効にする
    • from astapi.staticfiles import StaticFiles
    • app.mount(“/html”, StaticFiles(directory=”/code/html”, html=True))
    • 上記のように追加することで http://localhost:8080/html/ で/code/htmlに保存されたindex.htmlが表示されるのでそのページに仕込んだjavascriptからFastAPIのAPIを利用することで、シングルページアプリケーションを実現することが出来る。

サンプルでは1の方法を採用して、ルートページを表示させるようにしている。2の方法をにするには@app.get(‘/’)の部分を他のパスに変更するか、レスポンスごと削除し、スタティックマウント先を’/’ルートにすると良い。

サンプルのようにHTMLテンプレートを利用したレスポンスがこちら。

Bootstrapでチョッピリレイアウトしてみた。

最初は2の方法が良いなと思ってみたけど、サンプルにあるようにエラーベージをHTMLでちゃんと表示させるにはテンプレートを使用した方が便利だし、どうせテンプレート使うならルートページもテンプレートで行こう!という結論となりました。

FastAPIの導入

前回記事より一ヶ月ほど経過してしまいましたが、また思いつきで調査勉強の没頭していたという適当な感じで休んでいました。やっぱりこういうものを習慣化するのは難しい……。

現在の作業項目としてdjangoによるがWEBアプリテンプレートがあるが、シングルページアプリケーションへの移行を考慮するなど次第にバックエンド側の比重が軽くなってきた。このためもう少し軽いバックエンドフレームワークをと言うことで検討を行いFastAPIの採用を検討することにした。

まだ不勉強なので、間違った比較かも知れないが下記のように比較できると思う。

djangoFastAPI
バックエンド主体の比較的規模の大きなWebアプリケーションに向いている
主にHTMLレスポンスで動的にWebページを表示できる
フロントエンド主体のWebアプリケーションに向いている
主にJSONレスポンスでWebAPIに特化。ブラウザに表示するためには別途テンプレートや静的HTML文書を用意し、API利用によるWebアプリを実現する
ユーザー認証、データベース利用など一般的なバックエンド機能が一通り揃っている状態。基本状態ではリクエストに応じてJSONオブジェクトを返すだけのAPIサーバー。
バックエンド機能はチュートリアルに沿って進めればある程度のものが出来る。
機能追加は容易ではあるが、ある程度の調査が必要なのと、複雑なライブラリ構造の理解がないと敷居が高い印象構造が比較的単純で分かりやすいため、機能追加は容易。ただしそれなりの調査も必要。
簡単な比較

例えば、Djangoではユーザー認証や管理画面が最初から用意されているが、それのデザインや振る舞いを変えたり認証方法をカスタムしたりするためには、フレームワークの約束事に沿ったカスタム方法を調査するなど、かなりの労力が必要になるが、FastAPIはそもそも準備されていないので、自分で作らなくてはならない。そのため後から機能追加などのカスタムは非常に容易という事になる(ただし出来上がりもそれなりのものになってしまうのは自己責任ということで)。また、フレームワーク的な約束もあまり細かくないので、作っていくうちにコードの構成が分かりにくくなってしまう危険もあるのではと思う。

実験用のサーバー構成は、色々解説があるが、こちらではもともとのDjangoテンプレートのDocker環境があるのでそちらをベースにDocker環境の構築を行う。

次回はFastAPI導入の準備としてDocker環境構築のメモを残しておきたいと思う。

FastAPIでDjangoのテンプレートアプリと同等のものを実現しようとすると、認証の仕組み、データベースアクセスの仕組みなどDjangoでは組み込まれていたものを個別に調査・勉強・実装を行わないといけない。
大変そうだけど、汎用的な仕組みの理解なので色々役に立ちそうと、前向きに考えておこう。