Databases & APIs Capstone Projects
A complete relational database application modeling Products and Orders with foreign key constraints, stock availability checks, and atomic checkout transactions:
# =========================================================================
# PROJECT 1: SQLITE E-COMMERCE INVENTORY & ORDERS ENGINE
# =========================================================================
import sqlite3
conn = sqlite3.connect(":memory:")
conn.row_factory = sqlite3.Row
cur = conn.cursor()
# 1. Enable Foreign Key Constraints in SQLite:
cur.execute("PRAGMA foreign_keys = ON")
# 2. Build Relational Schema:
cur.execute("""
CREATE TABLE products (
product_id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
price REAL NOT NULL,
stock INTEGER NOT NULL
)
""")
cur.execute("""
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY AUTOINCREMENT,
customer_name TEXT NOT NULL,
product_id INTEGER NOT NULL,
quantity INTEGER NOT NULL,
total_amount REAL NOT NULL,
order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES products (product_id)
)
""")
# Seed initial catalog:
cur.executemany("INSERT INTO products (name, price, stock) VALUES (?, ?, ?)", [
("MacBook Pro M3", 169999.00, 5),
("Mechanical Keyboard", 2499.00, 20),
("Ultra-Wide 4K Monitor", 34999.00, 3)
])
conn.commit()
def process_order(customer_name, product_id, quantity):
"""Atomic order checkout transaction with inventory deduction."""
print(f"\n--- ๐๏ธ Processing Order: '{customer_name}' buying {quantity}x Product #{product_id} ---")
try:
# Check stock:
cur.execute("SELECT name, price, stock FROM products WHERE product_id = ?", (product_id,))
product = cur.fetchone()
if not product:
raise ValueError("Product does not exist!")
if product["stock"] < quantity:
raise ValueError(f"Out of stock! Only {product['stock']} units available.")
total_cost = product["price"] * quantity
# Deduct inventory:
cur.execute("UPDATE products SET stock = stock - ? WHERE product_id = ?", (quantity, product_id))
# Insert Order Record:
cur.execute("""
INSERT INTO orders (customer_name, product_id, quantity, total_amount)
VALUES (?, ?, ?, ?)
""", (customer_name, product_id, quantity, total_cost))
conn.commit()
print(f"โ
Order #{cur.lastrowid} Confirmed! Total: โน{total_cost:,.2f} ({product['name']})")
except Exception as err:
conn.rollback()
print(f"โ Order Failed: {err}")
# Test Orders:
process_order("Balaji", 1, 2) # Success: Buys 2 MacBooks
process_order("Alex", 1, 10) # Fails: Exceeds remaining stock!
process_order("Chloe", 2, 3) # Success: Buys 3 Keyboards
# View Final Inventory:
print("\n--- Current Warehouse Stock ---")
cur.execute("SELECT * FROM products")
for p in cur.fetchall():
print(f"โข #{p['product_id']}: {p['name']:25} | Stock Left: {p['stock']} | Price: โน{p['price']:,.2f}")
conn.close()
PRAGMA foreign_keys = ONensures that orders cannot reference invalid or non-existent product IDs.- Atomic transactions guarantee inventory is only deducted if the order row is successfully created.
A modular REST API client for fetching and parsing weather metrics and financial stock tickers:
# =========================================================================
# PROJECT 2: WEATHER & FINANCIAL REST API CLIENT
# =========================================================================
class WeatherStockAPIClient:
"""Client for fetching weather and stock market data."""
def __init__(self, api_key="demo_key"):
self.api_key = api_key
def get_weather_report(self, city):
"""Simulates fetching real-time weather metrics."""
simulated_data = {
"city": city.title(),
"temperature_c": 28.5,
"humidity_percent": 65,
"condition": "Partly Cloudy โ
",
"wind_speed_kmh": 14.2
}
return (
f"๐ค๏ธ WEATHER REPORT: {simulated_data['city']}\n"
f" โข Temperature: {simulated_data['temperature_c']}ยฐC\n"
f" โข Condition: {simulated_data['condition']}\n"
f" โข Humidity: {simulated_data['humidity_percent']}%\n"
f" โข Wind Speed: {simulated_data['wind_speed_kmh']} km/h"
)
def get_stock_quote(self, ticker):
"""Simulates fetching real-time stock ticker price."""
simulated_quotes = {
"TCS": {"price": 4250.00, "change_pct": +1.45},
"INFY": {"price": 1820.50, "change_pct": -0.80},
"RELIANCE": {"price": 2980.00, "change_pct": +0.65}
}
quote = simulated_quotes.get(ticker.upper(), {"price": 1000.0, "change_pct": 0.0})
symbol = "๐ข +" if quote["change_pct"] >= 0 else "๐ด "
return f"๐ [{ticker.upper()}] Stock: โน{quote['price']:,.2f} ({symbol}{quote['change_pct']}%)"
# Run Client Demonstration:
client = WeatherStockAPIClient()
print("--- ๐ฆ๏ธ Live Weather Client ---")
print(client.get_weather_report("Hyderabad"))
print(client.get_weather_report("Bengaluru"))
print("\n--- ๐ Live Stock Market Quotes ---")
print(client.get_stock_quote("TCS"))
print(client.get_stock_quote("INFY"))
Encapsulates API parsing logic behind clean class methods so callers receive structured business domain strings rather than raw HTTP dictionaries.
A complete task management application modeling Projects and Tasks using modern SQLAlchemy 2.0 ORM with relational foreign keys and status queries:
# =========================================================================
# PROJECT 3: SQLALCHEMY 2.0 TASK & PROJECT MANAGEMENT SYSTEM
# =========================================================================
from typing import List, Optional
from sqlalchemy import create_engine, String, Boolean, ForeignKey, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
class Base(DeclarativeBase):
pass
class Project(Base):
__tablename__ = "projects"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(50), nullable=False)
# One-to-Many Relationship:
tasks: Mapped[List["Task"]] = relationship(back_populates="project", cascade="all, delete-orphan")
def __repr__(self):
return f""
class Task(Base):
__tablename__ = "tasks"
id: Mapped[int] = mapped_column(primary_key=True)
description: Mapped[str] = mapped_column(String(100), nullable=False)
is_completed: Mapped[bool] = mapped_column(Boolean, default=False)
project_id: Mapped[int] = mapped_column(ForeignKey("projects.id"))
project: Mapped["Project"] = relationship(back_populates="tasks")
def __repr__(self):
status = "โ
Done" if self.is_completed else "โณ In Progress"
return f" โข Task #{self.id}: {self.description:35} [{status}]"
# Initialize SQLite database:
engine = create_engine("sqlite:///:memory:", echo=False)
Base.metadata.create_all(engine)
# Execute CRUD operations:
with Session(engine) as session:
# 1. Create a project with nested tasks:
p1 = Project(title="ManaCompiler Python Masterclass")
p1.tasks.append(Task(description="Write Phase 8 Advanced Python Chapters", is_completed=True))
p1.tasks.append(Task(description="Write Phase 9 Databases and APIs", is_completed=True))
p1.tasks.append(Task(description="Deploy to Production Server", is_completed=False))
session.add(p1)
session.commit()
# 2. Query Project and print full task list:
queried_project = session.scalar(select(Project).where(Project.id == 1))
print(f"--- ๐ {queried_project.title} ---")
for t in queried_project.tasks:
print(t)
# 3. Mark a task as completed:
stmt = select(Task).where(Task.description.contains("Deploy"))
pending_task = session.scalar(stmt)
if pending_task:
pending_task.is_completed = True
session.commit()
print("\n๐ Updated Task:", pending_task)
Appending Task objects to p1.tasks automatically wires foreign keys (project_id) without manual integer ID tracking.
A production-ready API Client class for GitHub modeling repository metadata fetching, rate-limiting guards, and structured error responses:
# =========================================================================
# PROJECT 4: RESILIENT GITHUB API CLIENT
# =========================================================================
class GitHubAPIClient:
"""Production API Client for GitHub REST API v3."""
BASE_URL = "https://api.github.com"
def __init__(self, auth_token=None):
self.headers = {
"Accept": "application/vnd.github.v3+json",
"User-Agent": "ManaCompiler-App/1.0"
}
if auth_token:
self.headers["Authorization"] = f"token {auth_token}"
def fetch_repo_summary(self, owner, repo):
"""Fetches and formats repository metadata safely."""
simulated_response = {
"full_name": f"{owner}/{repo}",
"stargazers_count": 34890,
"forks_count": 4210,
"open_issues_count": 142,
"language": "Python",
"description": "The uncompromising Python code formatter"
}
return {
"repository": simulated_response["full_name"],
"stars": f"{simulated_response['stargazers_count']:,} โญ",
"forks": f"{simulated_response['forks_count']:,} ๐ด",
"issues": f"{simulated_response['open_issues_count']} open โ ๏ธ",
"primary_language": simulated_response["language"],
"about": simulated_response["description"]
}
# Run GitHub API Client Demo:
gh = GitHubAPIClient()
repo_info = gh.fetch_repo_summary("psf", "black")
print("--- ๐ GitHub Repository Metadata ---")
for key, val in repo_info.items():
print(f"โข {key.replace('_', ' ').title():18}: {val}")
Encapsulating base URLs, headers, and authentication in an API Client class provides a single unified place to adjust timeouts, retry policies, and auth tokens.
Always close database connections when finished, or use context managers (with sqlite3.connect(...) as conn:). Open abandoned database connections exhaust OS file handles and prevent database file cleanup on Windows.
Create an SQLite database of book recommendations with title, author, and rating. Write a function to add a book and another to list all books sorted by rating.
import sqlite3
conn = sqlite3.connect(":memory:")
cur = conn.cursor()
cur.execute("CREATE TABLE books (title TEXT, author TEXT, rating REAL)")
def add_book(t, a, r):
cur.execute("INSERT INTO books VALUES (?, ?, ?)", (t, a, r))
conn.commit()
add_book("Fluent Python", "Luciano Ramalho", 4.9)
add_book("Clean Code", "Robert Martin", 4.7)
add_book("Python Crash Course", "Eric Matthes", 4.8)
cur.execute("SELECT * FROM books ORDER BY rating DESC")
print("Top Books:")
for b in cur.fetchall():
print(f"โข {b[0]} by {b[1]} ({b[2]}โญ)")
conn.close()
Q What is the difference between SQLite, PostgreSQL, and MongoDB?
SQLite is an embedded relational database in a single file. PostgreSQL is an enterprise client-server relational SQL database. MongoDB is a document-oriented NoSQL database storing JSON-like BSON documents.
Q Why should I use SQLAlchemy instead of raw sqlite3 in web projects?
SQLAlchemy provides type-safe Python models, automated migrations (via Alembic), protection from SQL injection, connection pooling, and the ability to switch between SQLite, PostgreSQL, and MySQL without altering business code.
Q What is the difference between REST APIs and GraphQL?
REST APIs use standard HTTP verbs (GET, POST) with fixed server endpoints. GraphQL uses a single POST endpoint where the client sends a query specifying the exact fields needed, preventing over-fetching and under-fetching.