Building a RESTful API with FastAPI, Pydantic, and Firestore
We’ll explore in this article how to build Restful API using FastAPI, Pydantic, and Google Firestore. A modern way for building APIs with Python, provides a powerful combination of speed, simplicity and accessibilty.
Setting Up the Environment : First, make sure you have Python 3.7 or above installed on your system. Before installing the dependencies for your project, it’s a good practice to create a virtual environment to isolate your project’s dependencies from other Python projects on your system.
To set up the requirements for the dependencies in your project, you can create a requirements.txt
file that lists all the packages and their versions. Here’s how you can do it for our FastAPI, Pydantic, and Firestore project :
fastapi==0.68.1
uvicorn==0.15.0
pydantic==1.9.0
google-cloud-firestore==2.3.2
uuid==1.30
Now, let’s define the model Item
that represents the structure of our data . We’ll ensure that the item id is generated server-side and remains private to prevent users from setting it manually. This approach enhances security and maintains consistency in our data model.
from pydantic import BaseModel, PrivateAttr
import uuid
class Item(BaseModel):
id: str= PrivateAttr(default_factory=lambda: str(uuid.uuid4()))
name: str
description: str
We’ve set a default factory for the id
field to generate a UUID when creating a new instance of the Item
model.
Now, let’s dive into the implementation of two crucial routes in our API: creating a new item and getting all items. These routes are fundamental for adding new data to our database and retrieving the existing data. Let’s explore how they work :
from fastapi import FastAPI, HTTPException
from google.cloud import firestore
from models import Item
# Initialize Firestore client
db = firestore.Client()
items_collection = db.collection('items')
# Initialize FastAPI app
app = FastAPI()
@app.post("/items/", response_model=Item)
async def create_item(item: Item):
item_data = item.dict()
items_collection.document(item.id).set(item.dict())
return Item(**users_ref.document(item.id).get().to_dict())
Inside create_item
we save the received item into a document in the Firestore collection items
and retrieve it to the user.
@app.get("/items/")
async def get_all_items():
items = []
for doc_item in items_collection.stream():
items.append(doc_item.to_dict())
return items
In Firestore, the stream()
method is used to retrieve documents from a collection in real-time. It returns an iterable that allows you to asynchronously iterate over the documents in the collection as they are added, updated, or removed.
It provides a powerful tool for building reactive applications and managing real-time data.
You ready to launch the FastAPI application with uvicorn. Assuming your FastAPI app is defined in a file named main.py
uvicorn main:app --reloaduvicorn main:app --reload
FastAPI provides interactive API documentation, including a Swagger UI generates documentation based on the structure and type hints of your API endpoints.
In conclusion, we can now create functional APIs very quickly. Still there are several ways we can enhance it to make it better. We can create a more robust, secure, and user-friendly FastAPI application that meets the needs of our users and exceeds their expectations. That we’ll discuss later. Let’s continue to iterate and refine our application to deliver the best possible experience for our users.