Chat
Search
Ithy Logo

FastAPI App with MongoDB Models

A comprehensive guide to integrate FastAPI with async MongoDB operations

mongodb fastapi code

Key Highlights

  • Environment Setup and Dependencies: Learn how to create a robust environment for FastAPI and MongoDB integration using Python, Virtual Environments, and the appropriate packages.
  • Data Modeling and CRUD Operations: Detailed steps on defining Pydantic models, establishing connections, and implementing CRUD (Create, Read, Update, Delete) endpoints.
  • Asynchronous Interaction: Utilize Motor, an asynchronous driver, for efficient and scalable MongoDB operations within FastAPI.

Introduction

In this guide, we will walk through the step-by-step process of building a FastAPI application complete with MongoDB models for data handling. The framework FastAPI, known for its high performance and ease of use, combined with MongoDB's NoSQL flexibility, allows the creation of powerful and scalable APIs. By following this guide, you will learn how to establish a connection to MongoDB, craft your models with Pydantic, implement essential CRUD endpoints, and deploy your application using an ASGI server like Uvicorn.


Setting Up Your Environment

Prerequisites and Installation

Before starting, ensure you are running Python 3.7 or later. FastAPI and its dependencies are designed to work on modern versions of Python. It is recommended to work within a virtual environment to keep your project dependencies isolated. You can use either venv or any other virtual environment tool of your choice.

Create and Activate Virtual Environment

Create your virtual environment and activate it using the commands:


  # Create a virtual environment
  python3 -m venv env
  
  # Activate the virtual environment on Unix or MacOS
  source env/bin/activate
  
  # Activate the virtual environment on Windows
  env\Scripts\activate
  

Install Required Libraries

With the environment activated, install the essential libraries with pip. You will need FastAPI, Uvicorn for running the application, and Motor to manage asynchronous MongoDB operations:


  pip install fastapi uvicorn motor
  

Project Structure and Overview

Organize your project to separate concerns and maintain a clear structure. A suggested project layout may look like this:

File/Folder Description
main.py Main application file where the FastAPI instance and routes are defined.
database.py Handles the MongoDB connection by initializing a Motor client.
models.py Contains Pydantic models used for data validation and serialization.
requirements.txt Lists the dependencies for the project.

This modular approach helps in maintaining clean code and allows for easier expansion later on.


MongoDB Connection Setup

Connecting to MongoDB

In order to interact with MongoDB asynchronously, create a module named "database.py" that handles the connection. This module will initialize the Motor client and provide access to your MongoDB database.

database.py

Add the following code to manage your MongoDB connection:


  # database.py
  from motor.motor_asyncio import AsyncIOMotorClient
  
  # Replace the connection string if you are using MongoDB Atlas or a different host.
  MONGO_DETAILS = "mongodb://localhost:27017"
  
  # Connect to the MongoDB server
  client = AsyncIOMotorClient(MONGO_DETAILS)
  
  # Access your database by name
  database = client.mydatabase
  

Model Definition with Pydantic

Defining Data Models

To facilitate data validation, conversion, and serialization, use Pydantic models. These models ensure that the data being received and returned by your API conforms to the specified schema. Create a "models.py" file where you will define your MongoDB models.

models.py

For this example, we will define a basic "ItemModel" and an "UpdateItemModel" to handle document operations:


  # models.py
  from pydantic import BaseModel
  from typing import Optional
  
  class ItemModel(BaseModel):
      id: Optional[str]
      name: str
      description: str
  
  class UpdateItemModel(BaseModel):
      name: Optional[str]
      description: Optional[str]
  

The ItemModel will be used for creating and representing items, while the UpdateItemModel will help update specific fields during an update operation.


Building API Endpoints in FastAPI

Designing CRUD Endpoints

With your database connection and data models ready, the next step is to build the API endpoints to perform CRUD operations (Create, Read, Update, Delete) on your MongoDB documents. All endpoints will be defined in your main.py file.

main.py

Below is a comprehensive example of how to create, read, update, and delete items within your FastAPI app:


  # main.py
  from fastapi import FastAPI, HTTPException
  from fastapi.responses import JSONResponse
  from bson import ObjectId
  from database import database
  from models import ItemModel, UpdateItemModel
  
  app = FastAPI()
  
  COLLECTION_NAME = "items"
  
  # Create Item
  @app.post("/items/", response_model=ItemModel)
  async def create_item(item: ItemModel):
      # Convert item to a dictionary and prepare for insertion
      item_dict = item.dict()
      
      # Insert item into MongoDB and retrieve its newly generated _id
      result = await database[COLLECTION_NAME].insert_one(item_dict)
      
      # Convert ObjectId to string for the response
      item_dict["id"] = str(result.inserted_id)
      return JSONResponse(content=item_dict, status_code=201)
  
  # Read All Items
  @app.get("/items/", response_model=list)
  async def read_all_items():
      items = await database[COLLECTION_NAME].find().to_list(1000)
      for item in items:
          item["id"] = str(item["_id"])
      return JSONResponse(content=items, status_code=200)
  
  # Read a Single Item
  @app.get("/items/{item_id}", response_model=ItemModel)
  async def read_item(item_id: str):
      item = await database[COLLECTION_NAME].find_one({"_id": ObjectId(item_id)})
      if item is None:
          raise HTTPException(status_code=404, detail="Item not found")
      item["id"] = str(item["_id"])
      return JSONResponse(content=item, status_code=200)
  
  # Update Item
  @app.put("/items/{item_id}", response_model=dict)
  async def update_item(item_id: str, item: UpdateItemModel):
      item_data = {key: value for key, value in item.dict().items() if value is not None}
      result = await database[COLLECTION_NAME].update_one(
          {"_id": ObjectId(item_id)},
          {"$set": item_data}
      )
      if result.modified_count == 0:
          raise HTTPException(status_code=404, detail="Item not found or no data updated")
      return JSONResponse(content={"message": "Item updated"}, status_code=200)
  
  # Delete Item
  @app.delete("/items/{item_id}", response_model=dict)
  async def delete_item(item_id: str):
      result = await database[COLLECTION_NAME].delete_one({"_id": ObjectId(item_id)})
      if result.deleted_count == 0:
          raise HTTPException(status_code=404, detail="Item not found")
      return JSONResponse(content={"message": "Item deleted"}, status_code=200)
  

This code sample implements all critical CRUD operations:

  • Create: Inserts a new document into MongoDB and returns the created item.
  • Read: Retrieves one or many documents from the collection.
  • Update: Modifies specific fields of an existing document.
  • Delete: Removes a document from the collection.

Running and Testing the Application

Launching the Server

Once your code is in place, run your application using Uvicorn. Execute the following command in your terminal:


  uvicorn main:app --host 0.0.0.0 --port 8000 --reload
  

The --reload flag allows the server to automatically reload whenever changes in the source code are detected. With the server running, you can access your API documentation, auto-generated by FastAPI, by navigating to:

http://127.0.0.1:8000/docs


Tips and Best Practices

Data Validation and Error Handling

Pydantic models enforce data validation automatically. However, it is important to add specific error handling routines when interacting with your database. Using FastAPI's exception handlers and HTTPException can improve the reliability of your API. Make sure to return meaningful error messages to help consumers of your API troubleshoot issues.

Handling MongoDB ObjectIDs

MongoDB’s _id field is of type ObjectId. In your application, convert these ObjectIds to their string counterparts before including them in JSON responses. When receiving data, convert strings back to ObjectIds as needed. This ensures consistency between your API and client-side applications.

Performance Considerations

Because FastAPI is asynchronous by design, integrating it with an async MongoDB driver like Motor boosts performance. For applications expecting high traffic, consider the following:

  • Implement pagination for endpoints returning large volumes of data.
  • Optimize MongoDB queries with appropriate indexes.
  • Monitor and log API performance to quickly identify bottlenecks.

Endpoint Overview Table

Endpoint HTTP Method Action
/items/ POST Create a new item
/items/ GET Retrieve all items
/items/{item_id} GET Retrieve a specific item
/items/{item_id} PUT Update an existing item
/items/{item_id} DELETE Delete a specific item

Resources and Additional Reading


Recommended Related Queries


Last updated March 14, 2025
Ask Ithy AI
Export Article
Delete Article