Building a CRUD API with FastAPI and MongoDB
Tags: python, mongodb, fastapi, learning
Published: 2024-07-05 21:30:11

Welcome, fellow developers! In this blog post, we'll dive into the exciting world of building RESTful APIs with FastAPI, a modern, fast, and easy-to-use framework, and MongoDB, a powerful NoSQL database. We'll create a simple CRUD (Create, Read, Update, Delete) API for managing a collection of books. Let's get started!

**1. Setting the Stage:**

- **Install Dependencies:** Begin by installing the required libraries:
  ```bash
  pip install fastapi uvicorn pymongo[srv]
  ```
- **Create Project Structure:**  Organize your project with a clear structure:
  ```
  my-book-api/
  ├── main.py
  ├── models.py
  └── schemas.py
  ```

**2. Defining Our Book Model:**

We'll start by defining our book model in `models.py`. This model represents the structure of our book data:

```python
from pydantic import BaseModel

class Book(BaseModel):
    title: str
    author: str
    description: str
    published_year: int

    class Config:
        schema_extra = {
            "example": {
                "title": "The Hitchhiker's Guide to the Galaxy",
                "author": "Douglas Adams",
                "description": "A humorous science fiction novel.",
                "published_year": 1979
            }
        }
```

**3. Database Connection:**

In `main.py`, we'll establish a connection to our MongoDB database:

```python
from fastapi import FastAPI
from pymongo import MongoClient

app = FastAPI()

client = MongoClient("mongodb+srv://<your_username>:<your_password>@<your_cluster>.mongodb.net/<your_database>?retryWrites=true&w=majority")
db = client["my_book_database"]
collection = db["books"]
```

**4. Creating the CRUD Operations:**

Now, let's define our CRUD endpoints within `main.py`:

**4.1. Creating a Book (POST):**

```python
@app.post("/books", response_model=Book)
async def create_book(book: Book):
  book_dict = book.dict()
  collection.insert_one(book_dict)
  return book
```

**4.2. Reading Books (GET):**

```python
@app.get("/books")
async def get_books():
  books = []
  for book in collection.find():
    books.append(Book(**book))
  return books
```

**4.3. Getting a Specific Book (GET):**

```python
@app.get("/books/{book_id}", response_model=Book)
async def get_book(book_id: str):
  book = collection.find_one({"_id": ObjectId(book_id)})
  if book:
    return Book(**book)
  else:
    raise HTTPException(status_code=404, detail="Book not found")
```

**4.4. Updating a Book (PUT):**

```python
@app.put("/books/{book_id}", response_model=Book)
async def update_book(book_id: str, book: Book):
  book_dict = book.dict()
  collection.update_one({"_id": ObjectId(book_id)}, {"$set": book_dict})
  return book
```

**4.5. Deleting a Book (DELETE):**

```python
@app.delete("/books/{book_id}")
async def delete_book(book_id: str):
  collection.delete_one({"_id": ObjectId(book_id)})
  return {"message": "Book deleted successfully"}
```

**5. Running the API:**

Finally, run the API using `uvicorn`:

```bash
uvicorn main:app --reload
```

**6. Testing the API:**

You can test your API using tools like Postman or curl. For example, to create a new book:

```bash
curl -X POST -H "Content-Type: application/json" -d '{"title": "The Lord of the Rings", "author": "J.R.R. Tolkien", "description": "A classic fantasy novel.", "published_year": 1954}' http://localhost:8000/books
```

**Tips and Tricks:**

- **Use a .env file:** Store sensitive information like database credentials in a `.env` file.
- **Implement error handling:** Handle potential errors with appropriate error messages and status codes.
- **Document your API:** Use tools like Swagger or OpenAPI to create documentation for your API.
- **Consider using a database driver for more robust connections and operations.**

**Conclusion:**

Creating CRUD operations with FastAPI and MongoDB is a simple yet powerful way to build RESTful APIs. By following these steps, you can quickly get your API up and running. Remember to explore additional features like pagination, filtering, and authentication for a more robust and user-friendly API. Happy coding!