Overview
FastAPI は、標準のPythonタイプのヒントを使用して API を構築するために設計された、最新の高パフォーマンス、本番環境に対応できる非同期Python Webフレームワークです。このチュートリアルでは、 MongoDBと FastAPI を統合した完全なCRUDアプリケーションを構築する方法を学びます。
非ブロッキング アーキテクチャ
FastAPI の非同期、非ブロッキング アーキテクチャにより、マルチスレッドに依存せずに数千の同時リクエストを処理できます。Python の asyncio
イベントループを使用し、コルーチンで同時実行性を管理します。これにより、アプリケーションはクエリが返されるのを待っている間、リクエストを一時停止することができます。これによりメモリ使用量が削減され、レイテンシを削減できます。
組み込みの機能と統合
FastAPI には、次のコンポーネントを含むいくつかの組み込み統合と機能があります。
自動データ解析、検証、直列化のためのPython
自動生成されインタラクティブAPIドキュメントのための OpenAPI とJSON schema
クリーンでテスト可能なコードのための軽量、Python 依存関係インジェクション システム
OAuth2 およびJSON web token の認証と認可のサポート
これらの機能により、開発を簡素化するために単数形のコードを最小限に抑えることができます。 FastAPI の機能の詳細については、 FastAPI のウェブサイト を参照してください。
Tutorial
このチュートリアルの完了したサンプルアプリは、 FastAPI を使用したMongoDBサンプルプロジェクトGitHubリポジトリにあります。
前提条件
このチュートリアルを開始する前に、次のコンポーネントがインストールされ、設定されていることを確認してください。
Python v3.9 - 3.11
MongoDB Atlasクラスター。クラスターのセットアップ方法について詳しくは、スタートガイドをご覧ください。
セットアップ
依存関係をインストールし、 MongoDBに接続して、 FastAPIサーバーを起動します 。
例コードの例の複製
ターミナルで次のコマンドを実行して、 mongodb-pymongo-fastapi GitHubリポジトリからコードを複製します。
git clone git@github.com:mongodb-developer/mongodb-pymongo-fastapi.git cd mongodb-pymongo-fastapi
必要な依存関係のインストール
Tip
仮想環境をアクティブ化する
Python依存関係を Atlas App Services がインストールすると、個々のプロジェクト向けにライブラリのバージョンをインストールできます。pip
コマンドを実行中前に、virtualenv
がアクティブであることを確認してください。
ターミナルで次のコマンドを実行して、requirements.txt
ファイルにリストされている依存関係をインストールします。
cd mongodb-pymongo-fastapi pip install -r requirements.txt
依存関係をダウンロードしてインストールするには、いくつか時間がかかる場合があります。
接続文字列を取得する
「MongoDB Atlas接続文字列の特定」ガイドに従って接続文字列を取得します。
ターミナルで次のコードを実行して、接続文字列を保存するための環境変数を作成します。
export MONGODB_URL="mongodb+srv://<username>:<password>@<url>/<db>?retryWrites=true&w=majority"
アプリケーションをクラスターに接続する
例アプリケーションのすべてのコードは、 mongodb-pymongo-fastapi GitHubリポジトリのアプリ.pyファイルに保存されます。
このコードを使用して、次のアクションを実行します。
MongoDB Atlasクラスターに接続するには、
AsyncMongoClient()
メソッドでMONGODB_URL
環境変数を使用し、college
という名前のデータベースを指定します。college
データベースへのポインターを作成します。students
コレクションへのポインターを作成する
client = AsyncMongoClient(os.environ["MONGODB_URL"],server_api=pymongo.server_api.ServerApi(version="1", strict=True,deprecation_errors=True)) db = client.get_database("college") student_collection = db.get_collection("students")
AsyncMongoClient()
呼び出しには、接続で Stable API機能を有効にするための server_api
パラメータが含まれています。配置にバージョン 5.0 以降のMongoDBサーバーが使用されていることを確認してください。詳細については、このガイドの「Stable API」セクションを参照してください。
データベースモデルの確認
このアプリケーションには、StudentModel
、UpdateStudentModel
、StudentCollection
の 3 つのモデルがあります。これらのモデルは app.py
ファイルで定義されています。
アプリケーション内のすべてのモデルは、基本的な型の検証、 JSON の解析と直列化、基本的なエラー処理を提供する Pytany 上で構築されます。BaseModel
ユーザーモデル クラス
StudentModel
は、過半数のエンドポイントの応答モデルとして使用されるプライマリ モデルです。
MongoDB、ドキュメントのデフォルトの識別子として _id
が使用されます。ただし、Python では、アンダースコアで始まるフィールド名はプライベート属性として扱われ、値を直接割り当てることはできません。これを回避するには、Python モデルでフィールドid
に名前を付けますが、_id
のエイリアスを指定することで、 MongoDBに正しくマッピングされます。
id
フィールドのタイプは PyObjectId
で、値を string に強制する BeforeValidator
で注釈が付けられたカスタムタイプです。これにより、MongoDB の ObjectId
がモデルによって適切に受け入れ、直列化できるようになります。
この設定には次の model_config
オプションが必要です。
populate_by_name=True
:フィールド名(id
)またはそのエイリアス(_id
)のいずれかを使用してモデルを初期化できるarbitrary_types_allowed=True
: などのカスタム タイプのサポートを有効にしますPyObjectId
id
フィールドも任意として定義され、デフォルト値は None
であるため、id
を指定せずに新しい StudentModel
インスタンスを作成できます。MongoDB はドキュメントが挿入されると _id
を自動的に生成し、この値はAPI応答で返されます。
model_config
には、FastAPI の自動生成 OpenAPI(Swaggre)ドキュメントで使用される例データを定義する json_schema_extra
設定も含まれています。
StudentModel
の定義は、app.py
ファイル内の次のコードで確認できます。
# Represents an ObjectId field in the database. # It will be represented as a `str` on the model so that it can be serialized to JSON. PyObjectId = Annotated[str, BeforeValidator(str)] class StudentModel(BaseModel): """ Container for a single student record. """ # The primary key for the StudentModel, stored as a `str` on the instance. # This will be aliased to ``_id`` when sent to MongoDB, # but provided as ``id`` in the API requests and responses. id: Optional[PyObjectId] = Field(alias="_id", default=None) name: str = Field(...) email: EmailStr = Field(...) course: str = Field(...) gpa: float = Field(..., le=4.0) model_config = ConfigDict( populate_by_name=True, arbitrary_types_allowed=True, json_schema_extra={ "example": { "name": "Jane Doe", "email": "jdoe@example.com", "course": "Experiments, Science, and Fashion in Nanophotonics", "gpa": 3.0, } }, )
Update Startupdate クラス
UpdateStudentModel
と StudentModel
とは次の重要な違いがあります。
変更できないため、
id
属性はありませんすべてのフィールドは任意であるため、更新するフィールドのみを指定できます
mongo_config
変数にはjson_encoders={ObjectId: str}
が含まれます
FastAPI はJSON string としてデータをエンコードおよびデコードします。これは MongoDB のBSONデータ型で保存できるすべてのデータ型をサポートしていません。BSON は、デフォルトのUUID 属性、_id
に使用される ObjectId
など、より多くのJSONネイティブ データ型をサポートしています。このため、ObjectId
オブジェクトは _id
フィールドに保存する前に string に変換する必要があります。json_encoders
の設定は Pydentic にこれを行うよう指示します。
BSONとJSONの比較の詳細については、 JSONとBSON MongoDB記事を参照してください。
UpdateStudentModel
の定義は、app.py
ファイル内の次のコードで確認できます。
class UpdateStudentModel(BaseModel): """ A set of optional updates to be made to a document in the database. """ name: Optional[str] = None email: Optional[EmailStr] = None course: Optional[str] = None gpa: Optional[float] = None model_config = ConfigDict( arbitrary_types_allowed=True, json_encoders={ObjectId: str}, json_schema_extra={ "example": { "name": "Jane Doe", "email": "jdoe@example.com", "course": "Experiments, Science, and Fashion in anophotonics", "gpa": 3.0, } }, )
SaturdayCollection クラス
StudentCollection
クラスは、StudentModel
インスタンスのリストをカプセル化するために定義されています。このエンドポイントの目的は、 JSON配列の処理方法を利用して機密データにアクセスしようとするJSONハイテク から一定の保護を提供することです。詳細については、 HaackedウェブサイトのJSON Hijacking に関する記事 をお読みください。
StudentCollection
の定義は、app.py
ファイル内の次のコードで確認できます。
class StudentCollection(BaseModel): """ A container holding a list of `StudentModel` instances """ students: List[StudentModel]
アプリケーション ルートの検討
次の表は、このアプリケーションで定義されているアプリケーションルートを説明しています。
route | アクション |
---|---|
| 新しい学生を作成する |
| すべての学生のリストを表示 |
| 単一の学生を表示 |
| 学生を更新する |
| 学生を削除する |
これらのルートは、次のセクションで説明されているように、app.py
ファイルで定義されています。
学生ルート
create_student
ルートは、 POST
リクエストで新しい学生データをJSON string として受け取ります。JSONリクエスト本体をPython辞書にデコードし、それをMongoDBクライアントに渡します。
insert_one
メソッドの応答には、新しく作成された学生の _id
が含まれます。このエンドポイントは post
修飾子呼び出しで response_model_by_alias=False
を指定しているため、id
として提供されます。新しい学生を挿入した後、メソッドは inserted_id
を使用して正しいドキュメントを検索し、これを JSONResponse
に返します。
FastAPI はデフォルトでHTTP 200
ステータス コードを返しますが、このルートは学生が作成されたことを明示的に示す 201
(「作成済み」)を返します。
create_student
の定義は、app.py
ファイル内の次のコードで確認できます。
async def create_student(student: StudentModel = Body(...)): """ Insert a new student record. A unique ``id`` will be created and provided in the response. """ new_student = student.model_dump(by_alias=True, exclude=["id"]) result = await student_collection.insert_one(new_student) new_student["_id"] = result.inserted_id return new_student
読み取りルート
このアプリケーションでは、すべての学生を表示するための 1 つのルートと、id
で指定された個々の学生を表示するための 1 つのルートがあります。
list_students
の定義は、app.py
ファイル内の次のコードで確認できます。
async def list_students(): """ List all the student data in the database. The response is unpaginated and limited to 1000 results. """ return StudentCollection(students=await student_collection.find().to_list(1000))
注意
結果のページ分割
この例ではto_list()
メソッドを使用します。ただし、実際のアプリケーションでは、結果をページ分割するために の skip と limitfind
のパラメーターを使用することをお勧めします。
学生詳細ルートには id
の path パラメーターがあり、FastAPI はこれを引数として show_student
関数に渡します。は、id
を使用して、データベース内の対応する学生を検索しようとします。
指定された id
のドキュメントが存在しない場合は、404
のステータスを持つ HTTPException
が発生します。
show_students
の定義は、app.py
ファイル内の次のコードで確認できます。
async def show_student(id: str): """ Get the record for a specific student, looked up by ``id``. """ if ( student := await student_collection.find_one({"_id": ObjectId(id)}) ) is not None: return student raise HTTPException(status_code=404, detail="Student {id} not found")
更新ルート
update_student
ルートは、create_student
ルートと show_student
ルートの組み合わせと同様に機能します。更新する学生の id
とJSON本文の新しいデータを受け取ります。
このルートは、受信したデータ内のすべてのパラメーターを反復処理し、提供されたパラメーターのみを変更します。 find_one_and_update() を $set メソッドに使用します。
更新するフィールドがない場合は、元の StudentModel
ドキュメントが返されます。更新または返す一致するドキュメントが見つからない場合は、404
エラーが発生します。
update_student
の定義は、app.py
ファイル内の次のコードで確認できます。
async def update_student(id: str, student: UpdateStudentModel = Body(...)): """ Update individual fields of an existing student record. Only the provided fields will be updated. Any missing or `null` fields will be ignored. """ student = { k: v for k, v in student.model_dump(by_alias=True).items() if v is not None } if len(student) >= 1: update_result = await student_collection.find_one_and_update( {"_id": ObjectId(id)}, {"$set": student}, return_document=ReturnDocument.AFTER, ) if update_result is not None: return update_result else: raise HTTPException(status_code=404, detail=f"Student {id} not found") # The update is empty, so return the matching document: if (existing_student := await student_collection.find_one({"_id": ObjectId(id)})) is not None: return existing_student raise HTTPException(status_code=404, detail=f"Student {id} not found")
削除ルート
delete_student
は単一のドキュメントに対して機能するため、 URLに id
を指定する必要があります。一致するドキュメントが見つかり、正常に削除されると、 HTTPステータス 204
(「コンテンツなし」)が返され、ドキュメントは返されません。指定された id
を持つ学生が見つからない場合は、404
エラーが返されます。
delete_student
の定義は、app.py
ファイル内の次のコードで確認できます。
async def delete_student(id: str): """ Remove a single student record from the database. """ delete_result = await student_collection.delete_one({"_id": ObjectId(id)}) if delete_result.deleted_count == 1: return Response(status_code=status.HTTP_204_NO_CONTENT) raise HTTPException(status_code=404, detail=f"Student {id} not found")
APIをテストする
アプリケーションの動作方法が理解できたら、エンドポイントの使用を開始できます。次の手順に従って、エンドポイントにリクエストを送信し、結果を確認します。
リクエストの送信
http://:127.0.0.1 8000/docs に移動します。次の画像は、FastAPIサーバーによって生成されたインターフェースを示しています。

リクエストを送信するエンドポイントのをクリックし、必要なパラメータを入力して、Execute をクリックします。Show Student エンドポイントでは、StudentModel.model_config
変数で定義されているサンプルデータを確認できます。
Tip
curl を使用してAPIをテストする
コマンドラインの使用を優先する場合は、次のような curl
コマンドを使用してリクエストを送信できます。
curl -X POST "http://127.0.0.1:8000/students/" \ -H "Content-Type: application/json" \ -d '{"name": "Jane Doe", "email": "jdoe@example.com", "course": "Physics", "gpa": 3.8}'
次のステップ
FastAPI がMongoDBおよびPyMongo Async ドライバーと統合する方法の基本が理解できたため、機能を追加できます。次のリストには、このアプリケーションに を追加する方法に関する提案がいくつか含まれています。
ベストプラクティス
次のセクションでは、FastAPI をMongoDBおよびPyMongo Async ドライバーと統合するためのいくつかのベストプラクティスについて説明します。
セキュリティと環境
アプリケーションコードで機密性の高い認証情報を直接保存すると、バージョン管理システムで誤って露出される可能性があります。代わりに、環境変数を使用して、接続文字列、 APIキー、その他の機密情報を保存します。
開発環境では、次のツールを使用して環境変数を管理できます。
directv :ディレクトリの入力時に ファイルから環境変数を自動的に読み込みます
.envrc
python-dotenv :
.env
Pythonアプリケーション内の ファイルから環境変数を読み込みますenvdir :ディレクトリ内のファイルから環境変数を設定します
サーバー選択 : 構成ファイルから環境変数をロード
どの環境変数制御ツールを選択するかにかかわらず、シークレットを含むファイル(.env
、.envrc
など)を .gitignore
ファイルに追加して、バージョン管理にコミットされるのを防ぎます。
本番環境には、 KMS(Key Management System) を使用します。また、開発環境で KMS ソリューションを使用してセキュリティを強化できます。
データベース接続ライフサイクル
FastAPIアプリケーションのスタートアップとシャットダウン イベントに応じてクライアント接続を初期化して閉じることで、 MongoDB接続のライフサイクルを適切に管理します。このアプローチは、モジュール レベルで接続を初期化するよりも堅牢です。
MongoDBクライアントを FastAPIアプリケーションオブジェクトにアタッチして、コードベース全体のすべてのパス操作関数からアクセスできるようにします。これにより、グローバル変数が不要になり、依存関係の管理が簡素化されます。
FastAPI の有効期限イベントを使用して接続管理を処理します。
import os from contextlib import asynccontextmanager from logging import info from fastapi import FastAPI from pymongo import AsyncMongoClient async def db_lifespan(app: FastAPI): # Startup app.mongodb_client = AsyncMongoClient(os.environ["MONGODB_URL"]) app.database = app.mongodb_client.get_default_database() ping_response = await app.database.command("ping") if int(ping_response["ok"]) != 1: raise Exception("Problem connecting to database cluster.") else: info("Connected to database cluster.") yield # Shutdown await app.mongodb_client.close() app: FastAPI = FastAPI(lifespan=db_lifespan)
BSONとJSON型の処理
MongoDBにJSONデータを提供する FastAPI エンドポイントには、 JSONでネイティブにサポートされていない ObjectId
型と Binary
型が含まれる場合があります。
ObjectId
は複数の方法で直列化できます。
文字列ベースの ID を使用する :
_id
フィールドでは、ObjectId
をJSON互換の文字列値に置き換えます。このアプローチは新しいアプリケーションには適していますが、既存のデータがある場合には適していない可能性があります。自動変換 : JSONに直列化するときに
ObjectId
値を string 表現に変換し、受信データを処理するときに string をObjectId
に解析します。ピリオド統合 : このチュートリアルの
PyObjectId
型に示されているように、Pydative の 型注釈 を使用して自動変換を処理します。オブジェクト ドキュメント マッパー(ODM) : Builder のような ODM
_id
ObjectId
を使用します。これでは、 フィールドでデフォルトで を使用することを想定しており、直列化と逆直列化を自動的に処理します。
データモデリング
柔軟性を維持するために、データベーススキーマをAPIスキーマから分離します。これにより、 APIインターフェイスを変更せずにMongoDBドキュメント構造を変更できます。
返されたBSONデータのフィールドを変換、検証、ドキュメント、フィルタリングするために、パス操作に Pythonクラスをresponse_model
として指定します。次のコード例は、この手法を実装する方法を示しています。
# A Pydantic class modelling the *response* schema. class Profile(BaseModel): """ A profile for a single user. """ id: Optional[str] = Field( default=None, description="MongoDB document ObjectID", alias="_id" ) username: str residence: str current_location: List[float] # A path operation that returns a Profile object as JSON. app = FastAPI() async def get_profile(profile_id: str) -> Mapping[str, Any]: # Uses response_model to automatically convert, validate, and document # the returned dict without manual Profile object creation. profile = await app.profiles.find_one({"_id": profile_id}) if profile is not None: # Return BSON document. FastAPI converts it automatically. return profile else: raise HTTPException( status_code=404, detail=f"No profile with id '{profile_id}'" )
その他のリソース
FastAPI 統合の詳細については、次のリソースを参照してください。
- MongoDB のフルスタック FastAPI アプリ ジェネレーター
MongoDB Community のサポートや貢献については、MongoDB Developer Community を参照してください。