Perfect 👍 — let’s do a side-by-side mini example comparing Flask vs FastAPI for the same RESTful API.
This will make it crystal clear how both frameworks work.
🎯 Goal: Build a simple API with two endpoints
GET /→ returns a welcome messageGET /items/{item_id}→ returns item details
🐍 1️⃣ Flask Example
# flask_app.py
from flask import Flask, jsonify, request
app = Flask(__name__)
@app.route('/', methods=['GET'])
def home():
return jsonify({"message": "Welcome to my Flask API!"})
@app.route('/items/<int:item_id>', methods=['GET'])
def get_item(item_id):
query = request.args.get('q')
return jsonify({"item_id": item_id, "query": query})
if __name__ == '__main__':
app.run(debug=True)
▶️ Run it:
python flask_app.py
Visit:
http://127.0.0.1:5000/http://127.0.0.1:5000/items/10?q=test
⚡ 2️⃣ FastAPI Example
# fastapi_app.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def home():
return {"message": "Welcome to my FastAPI!"}
@app.get("/items/{item_id}")
def get_item(item_id: int, q: str = None):
return {"item_id": item_id, "query": q}
▶️ Run it:
uvicorn fastapi_app:app --reload
Visit:
http://127.0.0.1:8000/http://127.0.0.1:8000/items/10?q=test
And best part —
📘 Auto docs:
- Swagger UI →
http://127.0.0.1:8000/docs - ReDoc →
http://127.0.0.1:8000/redoc
⚔️ Flask vs FastAPI Comparison
| Feature | Flask | FastAPI |
|---|---|---|
| Type | Micro web framework | Modern async API framework |
| Performance | Slower (sync) | Much faster (async) |
| Data Validation | Manual | Automatic (via Pydantic) |
| Auto Docs | ❌ No | ✅ Yes (/docs) |
| Ease for REST APIs | Good | Excellent |
| Best Use Case | Small/simple APIs | Modern microservices, AI/ML APIs |
✅ Verdict:
- If you’re learning or doing small projects → Flask is great.
- For production-grade, modern API development (especially for AI, data apps, or async systems) → FastAPI is the best choice.
Now we extend this example to include a POST API (for adding new items to a list/dictionary in memory)?
It’ll show how data is sent via JSON to the backend — a core REST concept.
Excellent 👌 — Let’s now extend both Flask and FastAPI examples to include a POST API that accepts JSON data and adds a new item to an in-memory list (or dictionary).
This shows how data flows from client → API → backend storage (list) — a key concept in REST.
🧩 Example Goal:
- Maintain a list of items
GET /items→ returns all itemsPOST /items→ add a new item (sent as JSON)
🐍 1️⃣ Flask Example (with POST)
# flask_post_api.py
from flask import Flask, jsonify, request
app = Flask(__name__)
# In-memory data store
items = [
{"id": 1, "name": "Pen", "price": 10},
{"id": 2, "name": "Notebook", "price": 50}
]
@app.route('/items', methods=['GET'])
def get_items():
return jsonify(items)
@app.route('/items', methods=['POST'])
def add_item():
data = request.get_json()
new_item = {
"id": len(items) + 1,
"name": data["name"],
"price": data["price"]
}
items.append(new_item)
return jsonify({"message": "Item added successfully", "item": new_item}), 201
if __name__ == '__main__':
app.run(debug=True)
▶️ Run:
python flask_post_api.py
Test via curl or Postman:
# GET all items
curl http://127.0.0.1:5000/items
# POST new item
curl -X POST http://127.0.0.1:5000/items \
-H "Content-Type: application/json" \
-d '{"name": "Pencil", "price": 5}'
⚡ 2️⃣ FastAPI Example (with POST)
# fastapi_post_api.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# In-memory data store
items = [
{"id": 1, "name": "Pen", "price": 10},
{"id": 2, "name": "Notebook", "price": 50}
]
# Define request body structure
class Item(BaseModel):
name: str
price: float
@app.get("/items")
def get_items():
return items
@app.post("/items")
def add_item(item: Item):
new_item = {
"id": len(items) + 1,
"name": item.name,
"price": item.price
}
items.append(new_item)
return {"message": "Item added successfully", "item": new_item}
▶️ Run:
uvicorn fastapi_post_api:app --reload
Test via browser or Postman:
GET http://127.0.0.1:8000/itemsPOST http://127.0.0.1:8000/items
JSON Body:{ "name": "Pencil", "price": 5 }
✅ Auto-docs:
- Swagger UI:
http://127.0.0.1:8000/docs - ReDoc:
http://127.0.0.1:8000/redoc
⚔️ Flask vs FastAPI – POST Comparison
| Feature | Flask | FastAPI |
|---|---|---|
| JSON Parsing | request.get_json() | Automatically handled |
| Input Validation | Manual | ✅ via Pydantic models |
| Auto Docs | ❌ No | ✅ /docs auto generated |
| Type Hints | Optional | Enforced for clarity |
| Speed | Slower | Faster (async) |
🧠 Summary
| Endpoint | Method | Description |
|---|---|---|
/items | GET | Fetch all items |
/items | POST | Add a new item via JSON |
Now we add a PUT (update) and DELETE API next — so you get a complete CRUD (Create, Read, Update, Delete) example in both Flask and FastAPI
Perfect ✅ — now we’ll complete the picture by adding PUT (update) and DELETE endpoints — giving you a full CRUD API in both Flask and FastAPI.
🧱 CRUD Overview
| Operation | HTTP Method | Description | Example Endpoint |
|---|---|---|---|
| Create | POST | Add new item | /items |
| Read | GET | Get items | /items |
| Update | PUT | Modify existing item | /items/{id} |
| Delete | DELETE | Remove item | /items/{id} |
🐍 1️⃣ Flask — Full CRUD Example
# flask_crud_api.py
from flask import Flask, jsonify, request
app = Flask(__name__)
# In-memory data
items = [
{"id": 1, "name": "Pen", "price": 10},
{"id": 2, "name": "Notebook", "price": 50}
]
# READ
@app.route('/items', methods=['GET'])
def get_items():
return jsonify(items)
# CREATE
@app.route('/items', methods=['POST'])
def add_item():
data = request.get_json()
new_item = {
"id": len(items) + 1,
"name": data["name"],
"price": data["price"]
}
items.append(new_item)
return jsonify({"message": "Item added", "item": new_item}), 201
# UPDATE
@app.route('/items/<int:item_id>', methods=['PUT'])
def update_item(item_id):
data = request.get_json()
for item in items:
if item["id"] == item_id:
item["name"] = data.get("name", item["name"])
item["price"] = data.get("price", item["price"])
return jsonify({"message": "Item updated", "item": item})
return jsonify({"error": "Item not found"}), 404
# DELETE
@app.route('/items/<int:item_id>', methods=['DELETE'])
def delete_item(item_id):
for item in items:
if item["id"] == item_id:
items.remove(item)
return jsonify({"message": f"Item {item_id} deleted"})
return jsonify({"error": "Item not found"}), 404
if __name__ == '__main__':
app.run(debug=True)
▶️ Run:
python flask_crud_api.py
⚡ 2️⃣ FastAPI — Full CRUD Example
# fastapi_crud_api.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
# In-memory data
items = [
{"id": 1, "name": "Pen", "price": 10},
{"id": 2, "name": "Notebook", "price": 50}
]
# Request model
class Item(BaseModel):
name: str
price: float
# READ
@app.get("/items")
def get_items():
return items
# CREATE
@app.post("/items")
def add_item(item: Item):
new_item = {"id": len(items) + 1, "name": item.name, "price": item.price}
items.append(new_item)
return {"message": "Item added", "item": new_item}
# UPDATE
@app.put("/items/{item_id}")
def update_item(item_id: int, updated_item: Item):
for item in items:
if item["id"] == item_id:
item["name"] = updated_item.name
item["price"] = updated_item.price
return {"message": "Item updated", "item": item}
raise HTTPException(status_code=404, detail="Item not found")
# DELETE
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
for item in items:
if item["id"] == item_id:
items.remove(item)
return {"message": f"Item {item_id} deleted"}
raise HTTPException(status_code=404, detail="Item not found")
▶️ Run:
uvicorn fastapi_crud_api:app --reload
Test via browser or Postman:
- GET →
http://127.0.0.1:8000/items - POST → Add a new item
{ "name": "Eraser", "price": 8 } - PUT → Update existing item
{ "name": "Blue Pen", "price": 12 } - DELETE → Remove item by ID
e.g.,DELETE /items/1
✅ Auto Docs:
http://127.0.0.1:8000/docshttp://127.0.0.1:8000/redoc
⚔️ Flask vs FastAPI — CRUD Comparison
| Feature | Flask | FastAPI |
|---|---|---|
| Setup | Simple | Slightly more setup (Pydantic) |
| Validation | Manual | ✅ Auto via model |
| Error Handling | Manual (if/else) | ✅ Built-in HTTPException |
| Docs UI | ❌ None | ✅ /docs & /redoc |
| Speed | Synchronous | ✅ Async support |
| Typing | Optional | ✅ Enforced |
🧠 Summary
✅ You now have:
- Flask CRUD API → Easy for beginners
- FastAPI CRUD API → Modern, production-grade
Both can serve as a backend for React, mobile apps, or AI services.
Now i will show next how to connect this FastAPI CRUD with a real database (like SQLite) — so data persists even after restart?
That’s the next step to make this a real-world API.
Perfect 💪 — now you’re moving from in-memory (temporary) data to persistent storage (real database).
We’ll connect both Flask and FastAPI to a SQLite database, which is lightweight, file-based, and great for learning or small projects.
🧱 Overview
| Framework | ORM/Library | DB Used | Description |
|---|---|---|---|
| Flask | SQLAlchemy | SQLite | Classic ORM for Flask |
| FastAPI | SQLModel (built on SQLAlchemy) | SQLite | Modern ORM, async-ready |
🐍 1️⃣ Flask CRUD API with SQLite (SQLAlchemy)
📦 Install dependencies
pip install flask sqlalchemy
🧩 Flask Code
# flask_crud_db.py
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# SQLite database configuration
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///items.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# Model definition
class Item(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
price = db.Column(db.Float, nullable=False)
def to_dict(self):
return {"id": self.id, "name": self.name, "price": self.price}
# Create database
with app.app_context():
db.create_all()
# CREATE
@app.route('/items', methods=['POST'])
def add_item():
data = request.get_json()
new_item = Item(name=data['name'], price=data['price'])
db.session.add(new_item)
db.session.commit()
return jsonify({"message": "Item added", "item": new_item.to_dict()}), 201
# READ
@app.route('/items', methods=['GET'])
def get_items():
all_items = Item.query.all()
return jsonify([item.to_dict() for item in all_items])
# UPDATE
@app.route('/items/<int:item_id>', methods=['PUT'])
def update_item(item_id):
data = request.get_json()
item = Item.query.get(item_id)
if not item:
return jsonify({"error": "Item not found"}), 404
item.name = data.get('name', item.name)
item.price = data.get('price', item.price)
db.session.commit()
return jsonify({"message": "Item updated", "item": item.to_dict()})
# DELETE
@app.route('/items/<int:item_id>', methods=['DELETE'])
def delete_item(item_id):
item = Item.query.get(item_id)
if not item:
return jsonify({"error": "Item not found"}), 404
db.session.delete(item)
db.session.commit()
return jsonify({"message": f"Item {item_id} deleted"})
if __name__ == '__main__':
app.run(debug=True)
▶️ Run:
python flask_crud_db.py
🧠 SQLite file created:
A file named items.db will appear in your working directory — that’s your database.
⚡ 2️⃣ FastAPI CRUD API with SQLite (SQLModel)
📦 Install dependencies
pip install fastapi uvicorn sqlmodel
🧩 FastAPI Code
# fastapi_crud_db.py
from fastapi import FastAPI, HTTPException
from sqlmodel import SQLModel, Field, Session, create_engine, select
# Define database and model
sqlite_url = "sqlite:///items.db"
engine = create_engine(sqlite_url, echo=True)
class Item(SQLModel, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str
price: float
# Create DB tables
SQLModel.metadata.create_all(engine)
app = FastAPI()
# CREATE
@app.post("/items")
def add_item(item: Item):
with Session(engine) as session:
session.add(item)
session.commit()
session.refresh(item)
return {"message": "Item added", "item": item}
# READ
@app.get("/items")
def get_items():
with Session(engine) as session:
items = session.exec(select(Item)).all()
return items
# UPDATE
@app.put("/items/{item_id}")
def update_item(item_id: int, updated_item: Item):
with Session(engine) as session:
item = session.get(Item, item_id)
if not item:
raise HTTPException(status_code=404, detail="Item not found")
item.name = updated_item.name
item.price = updated_item.price
session.commit()
session.refresh(item)
return {"message": "Item updated", "item": item}
# DELETE
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
with Session(engine) as session:
item = session.get(Item, item_id)
if not item:
raise HTTPException(status_code=404, detail="Item not found")
session.delete(item)
session.commit()
return {"message": f"Item {item_id} deleted"}
▶️ Run:
uvicorn fastapi_crud_db:app --reload
Visit:
- Swagger UI → http://127.0.0.1:8000/docs
- ReDoc → http://127.0.0.1:8000/redoc
✅ Database file items.db will be created automatically.
⚔️ Flask vs FastAPI with DB — Comparison
| Feature | Flask + SQLAlchemy | FastAPI + SQLModel |
|---|---|---|
| DB Connection | SQLAlchemy ORM | SQLModel (built on SQLAlchemy) |
| Async Support | ❌ No | ✅ Optional |
| Schema Validation | Manual | ✅ Automatic via type hints |
| Auto Docs | ❌ No | ✅ /docs |
| Learning Curve | Easy | Slightly steeper |
| Ideal Use | Traditional Web Apps | Modern APIs / AI Backends |
🧠 Summary
✅ You now know:
- How to build CRUD APIs
- How to store data persistently in SQLite
- How to use ORM (Object Relational Mapping) in both Flask & FastAPI
Leave a Reply