0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【FastAPI】Pythonのバックエンドフレームワークを学ぶ①

Posted at

FastAPIとは?

バックエンドAPIの開発において以下の技術の有難さを痛いほど分かっている人にとっては今更感あります。
この記事はAPIを作った経験がない入門者に向けて、FastAPI1の解説を分かりやすく書いています。

  • Python decolator
  • Hot Reload
  • Swagger
  • Dependency機能

Python decolator

PythonのWebフレームワークでどこでも出てくるデコレータ。
以下のような@app.<method>(path)という見た目をしています。

app = FastAPI()

@app.get("/post/")
def getPost(id):
    return {"id": id, "title": "A title has to be bold style."}

@app.get=(appインスタンスのgetメソッド)なのでその実装を辿ると、APIルートとしてラップされた関数を追加しているようです。つまり、appインスタンスはHTTPのメソッドとパスが一致している場合に、デコレータでラップされた関数を呼び出します。

Pythonのデコレータは単なる糖衣構文です。
関数内の処理結果や関数自体をトラッキングするための方法と考えておけば無難です。

最初は戸惑いますけどね・・・。

Hot Reload

ReactやFlutterを触ったことのある人はその時の体験を思い出してみてください。
Hot Reloadはソースコードの変更箇所を検知して、変更前の情報をできるだけ保持したまま再読み込みができる機能です。開発段階で間違ったコードを書いたとしても、修正結果を素早く反映できます。

例えば、投稿型サービスを作る際に、ゲストには投稿権限をつけないとします。
この機能を実装するためには、以下のように現在のユーザに依存(Depends)させます。

from fastapi import Depends

@app.post("/post/")
- def addPost(title, content):
+ def addPost(title, content, current_user: User = Depends(get_current_user)):
      id = Post.add(title, content)
      return {"id": id}

この変更を行ってファイルを保存した際、現在ログインしていないユーザの投稿操作が即座にブロックされます。

IDEに付いてくるRunボタンは最初のステートに戻ってしまいますが、Hot Reloadはステートを保持できるので開発体験が向上します。

Swagger

SwaggerはAPIのPlayground兼ドキュメントだと思ってください。Gitbookなどのエンタープライズ向け文書化ツールにはAPIエンドポイント専用のテンプレートが存在しますが、自分で書き込む必要があります。

Swaggerでは定義したエンドポイントをすぐに確認できるのでとても便利です。こんな感じに見れるよ。
(とりあえず作ってる途中のやつをあげIとは?
バックエンドAPIの開発において以下の技術の有難さを痛いほど分かっている人にとっては今更感あります。
この記事はAPIを作った経験がない入門者に分かりやすく書いています。

  • Python decolator
  • Hot Reload
  • Swagger
  • Dependency機能

Python decolator

PythonのWebフレームワークでどこでも出てくるデコレータ。
以下のような@app.<method>(path)という見た目をしています。

app = FastAPI()

@app.get("/post/")
def getPost(id):
    return {"id": id, "title": "A title has to be bold style."}

@app.get=(appインスタンスのgetメソッド)なのでその実装を辿ると、APIルートとしてラップされた関数を追加しているようです。つまり、appインスタンスはHTTPのメソッドとパスが一致している場合に、デコレータでラップされた関数を呼び出す処理をします。

Pythonのデコレータは単なる糖衣構文です。
関数内の処理結果や関数自体をトラッキングするための方法と考えておけば無難です。

最初は戸惑いますけどね・・・。

Hot Reload

ReactやFlutterを触ったことのある人はその時の体験を思い出してみてください。
Hot Reloadはソースコードの変更箇所を検知して、変更前の情報をできるだけ保持したまま再読み込みができる機能です。開発段階で間違ったコードを書いたとしても、修正結果を素早く反映できます。

例えば、投稿型サービスを作る際に、ゲストには投稿権限をつけないとします。
この機能を実装するためには、以下のように現在のユーザに依存(Depends)させます。

from fastapi import Depends

@app.post("/post/")
- def addPost(title, content):
+ def addPost(title, content, current_user: User = Depends(get_current_user)):
      id = Post.add(title, content)
      return {"id": id}

この変更を行ってファイルを保存した際、現在ログインしていないユーザの投稿操作が即座にブロックされます。

IDEに付いてくるRunボタンは最初のステートに戻ってしまいますが、Hot Reloadはステートを保持できるので開発体験が向上します。2

Swagger

SwaggerはAPIのPlayground兼ドキュメントだと思ってください。Gitbookなどのエンタープライズ向け文書化ツールにはAPIエンドポイント専用のテンプレートが存在しますが、自分で書き込む必要があります。

Swaggerでは定義したエンドポイントをすぐに確認できるのでとても便利です。こんな感じに見れるよ。
(とりあえず見栄えが良さそうなものを)

swaggerui_sample.png

Example Valueの参照元

型ヒントで指定します。

まずpydanticやtypingなどのスキーマを定義するモジュールをインポートしましょう。

from pydantic import BaseModel, Field
from typing import List, Dict

次にBaseModelを継承しスキーマを定義します。

class Timeline(BaseModel):
    similarityArray: List[int] = Field([],
                                       example=[1, 2],
                                       description='content ranking over the given query')
    dateArray: List[int] = Field([],
                                 example=[2, 1],
                                 description='content timeline')
    metadata: Dict[int, Metadata] = Field({}, example={1: Metadata()})

以下の関数において、返り値の型であるTimelineBaseModelを継承しているので、Swagger UIのExample Valueにスキーマのサンプル値が表示されます。

@app.put("/v1/timeline/")
def get_timeline(query: TimelineQuery) -> Timeline:
    return Timeline()

FastAPIはスキーマや型をきっちり書くことを前提に設計されているような印象を受けます。3
Swagger UIに説明を集約できるメリットはぜひ活用したいですね。

Dependency機能

新しいポストをデータベースからフェッチしたい場合、どうしたらよいでしょうか?
少し、情報を整理します。

  • FastAPIのデコレータを使用すると、ポストを取得するエンドポイントを作成できます。
  • 引数には、クエリパラメータを指定します。

では、データベースはどうやって関数に渡すのかというと、FastAPIのDependsクラスを利用します。
以下の関数では、ユーザとデータベースをAPIルートに依存させています。

@app.get(path="/users/", tags=["Users"])
async def users(current_user: str = Depends(get_current_user),
                session: Session = Depends(get_db)):
    return User.getUserInfo(session, current_user)

こうすることで、

  1. ログインが必要であること
  2. データベース操作を含むこと

を明示でき、意図がつかみやすいソースコードになっています。

文字通り、Dependsクラスは依存対象を表現する手段だと考えてください。

第一回のまとめ

✅ Pythonのデコレータは関数内の処理結果や関数自体をトラッキングするための表現方法の一つです。
✅ Hot Reloadはステートを保持できるので開発体験が向上します。
✅ 型やスキーマをきっちり書くことで、Swagger UIにドキュメントを集約できます。
✅ Dependsクラスは依存対象を表現する手段です。

  1. Pythonはデータサイエンスに強い言語だと言われていますが、バックエンドAPIを実装する言語としても全然いけると思います。

  2. FastAPIのHot Reloadは、より正確にはuvicornが担っている役割なので、ビルトインで実装されている機能ではないことに注意しましょう。

  3. Pythonは動的型付け言語ですが、型ヒントのニーズがある開発シーンにも対応できます。

0
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?