🇯🇵

FastAPI×MongoDBを用いたAPI開発の手ほどき② 〜DB接続〜

2024/02/29に公開

はじめに

こんにちは。LIRIS株式会社で取締役兼エンジニアをしています田村です。
前回投稿した「FastAPI×MongoDBを用いたAPI開発の手ほどき① 〜環境構築〜」の続きを書いていきます。初めての方は是非前回分から見ていただければと思います。
今回は、FastAPIとMongoDBを接続し、実際にCRUD操作を実装します。

コードだけ見たいという方はこちらから取得してください。

想定読者

  • PythonでWeb API開発したい、されている方
  • FastAPIに興味のある方、数年使っている方
  • パフォーマンス向上に興味のある方

フォルダ・ファイル構成

今回は、DBとの接続行いますので以下の構成でフォルダ、ファイルを作成します。
appフォルダ内にdbフォルダを作成し、dbフォルダ内にsession.pyを作成します。
また、appフォルダ内にconfig.pyを作成します。

fastapi-mongo-example/
├ app/
│ ├ db/
│ │ └ session.py
│ ├ .dockerignore
│ ├ logging.conf
│ ├ config.py
│ ├ main.py
│ ├ poetry.lock
│ ├ pyproject.toml
│ ├ start.sh
│ └ Dockerfile
├ .gitignore
└ docker-compose.yml

config.pyの作成

config.pyにはアプリケーションで利用する環境変数などをまとめます。
今回はDB接続に必要な情報をまとめます。

from pydantic import Field
from pydantic_settings import BaseSettings


class DBConfig(BaseSettings):
    DB_USERNAME: str = Field(description="DBのユーザ名")
    DB_PASSWORD: str = Field(description="DBのパスワード")
    DB_HOST: str = Field(description="DBのホスト名")
    DB_PORT: str = Field(description="DBのポート番号")


db_config = DBConfig()

Pydantic_settingsは環境変数を管理するのに便利です。
デフォルト値やバリデーション、説明書きなどを設定できますのでおすすめです。

docker-compose.ymlの内容変更

docker-compose.ymlのenvironmentの内容に、先程config.pyに記述した環境変数を追記していきます。
長くなるので、fastapiコンテナの設定のみ記載します。

version: "3.8"

services:
  fastapi:
    image: "fastapi:${TAG-latest}"
    links:
      - mongo
    build:
      context: ./app
      dockerfile: Dockerfile
    ports:
      - 8000:8000
    volumes:
      - ./app:/app:cached
    environment:
      HOST: 0.0.0.0
      PORT: 8000
      LOG_LEVEL: info
      LOGCONFIG: ./logging.conf
      WORKERS: 1
      APP_MODULE: main:app
      DB_USERNAME: admin
      DB_PASSWORD: password
      DB_HOST: mongo
      DB_PORT: 27017
    tty: true
    restart: unless-stopped

session.pyの作成

session.pyにはDB接続情報を記述していきます。
app/db/session.pyを作成し、以下のように記述します。
PythonでMongoDBを扱うのにpymongoライブラリを利用しています。

from urllib import parse

from config import db_config
from pymongo import MongoClient
from pymongo.database import Database

USER_NAME = parse.quote_plus(db_config.DB_USERNAME)
PASSWORD = parse.quote_plus(db_config.DB_PASSWORD)
HOST = db_config.DB_HOST
PORT = db_config.DB_PORT

MONGO_DATABASE_URL: str = f"mongodb://{USER_NAME}:{PASSWORD}@{HOST}:{PORT}"

client = MongoClient(MONGO_DATABASE_URL)


def get_db() -> Database:
    """DB取得

    Returns:
        Database: データべース
    """
    db: Database = client.db
    return db

main.pyの修正

APIをシャットダウンする時にDBのセッションも一緒に切断するように、main.pyに記述します。
@app.on_eventデコレータ を用いてシャットダウン時の動作を定義しています。

from db.session import client
from fastapi import FastAPI

app = FastAPI(
    title="FastAPI Sample",
)


@app.on_event("shutdown")
def shutdown_event():
    client.close()


@app.get("/", status_code=200)
def root():
    return "成功!"

DBにデータを登録してみる

エンドポイント追加

DBに接続できているか確認してみます。
main.pyに /box のPOSTメソッドとGETメソッドを追加して動作確認します。

from db.session import client, get_db
from fastapi import FastAPI

app = FastAPI(
    title="FastAPI Sample",
)


@app.on_event("shutdown")
def shutdown_event():
    client.close()


@app.get("/", status_code=200)
def root():
    return "成功!"


@app.post("/box", status_code=200)
def post_item_in_box(item: str):
    # dbというデータベースを取得
    db = get_db()
    # データベースにデータを追加
    result = db["box"].insert_one({"item": item})
    return {"id": str(result.inserted_id)}


@app.get("/box", status_code=200)
def get_items_in_box():
    # dbというデータベースを取得
    db = get_db()
    # データベースからデータを取得
    items = db["box"].find()
    # データを整形
    results = [{"id": str(item["_id"]), "item": item["item"]} for item in items]
    return results

"id"をstr型に変換していますが、これはMongoDBのデフォルトのIDがObjectIDという形式になっており、ObjectIDのままでは返せないので、strに変換しています。
ここの効率的な処理も今後紹介していきます。

動作確認

docker-compose up -d でDockerコンテナを起動します。
http://localhost:8000/docsにアクセスして、Swagger UIが立ち上がっていれば下図のように表示されます。
先ほど追加した /box のPOSTメソッドとGETメソッドが増えています。

docs

まずはPOSTメソッドでデータを登録します。

  1. 緑の /boxPOSTメソッドをクリック
  2. 右側に"Try it out"のボタンが表示されますので、そのボタンをクリック
  3. item 欄に好きな文字列を入力
  4. 最後に下の青い"Execute"ボタンをクリック

これで記念すべきデータ第1号が登録されました。
本当に登録されているか確認しましょう。
GETメソッドを実行します。

  1. 青い /boxGETメソッドをクリック
  2. 右側に"Try it out"のボタンが表示されますので、そのボタンをクリック
  3. 最後に下の青い"Execute"ボタンをクリック

正常に処理が完了していれば、登録したitemが表示されます。

mongoexpressでDBを確認

mongoexpressというGUIツールを使うことで、APIを経由しなくても簡単にMongoDBの中身を確認できます。
第1回目でDockerの設定はしていました。
http://localhost:8081/にアクセスすると下図のように表示されます。

mongoexpress

db の"View"をクリックしてみると、先程作成した box コレクションが表示されます。
MongoDBでは、RDBで言うところのテーブルに当たるものがコレクションです。
では、”View”をクリックすると先程登録したデータが入っていると思います。
MongoDBでは、RDBで言うところのレコードに当たるものがドキュメントになります。

※ mongoexpressを本番環境では利用せず、開発環境のみで利用するようにしましょう。

まとめ

今回実施したこと

  1. Pydantic_settingsを用いた環境変数管理
  2. MongoDBとの接続
  3. MongoDBの動作確認
  4. mongoexpressの紹介

ここまでのコードはこちらから取得できます。

次回は Pydantic を使ったスキーマ作成を予定しています。

この記事を読んでみて何か学びが得られれば幸いです。

Discussion