Web Development Capstone Projects
A complete blog application featuring Post creation, dynamic slug generation, author relationships, tag filtering, and publication status management:
# =========================================================================
# PROJECT 1: MULTI-AUTHOR BLOG APPLICATION ENGINE
# =========================================================================
import datetime
class BlogPost:
"""Models an individual blog article."""
def __init__(self, post_id, title, content, author, tags=None):
self.id = post_id
self.title = title
self.slug = title.lower().replace(" ", "-")
self.content = content
self.author = author
self.tags = tags or []
self.created_at = datetime.datetime.now()
self.is_published = True
self.views = 0
def record_view(self):
self.views += 1
def __repr__(self):
return f""
class BlogEngine:
"""Manages publishing, querying, and filtering blog articles."""
def __init__(self):
self.posts = []
self._next_id = 1
def publish_post(self, title, content, author, tags=None):
post = BlogPost(self._next_id, title, content, author, tags)
self.posts.append(post)
self._next_id += 1
print(f"๐ Published: '{post.title}' by {author}")
return post
def get_by_slug(self, slug):
for p in self.posts:
if p.slug == slug and p.is_published:
p.record_view()
return p
return None
def filter_by_tag(self, tag):
return [p for p in self.posts if tag.lower() in [t.lower() for t in p.tags] and p.is_published]
# Run Project 1 Demonstration:
blog = BlogEngine()
p1 = blog.publish_post("Mastering Python 3 in 2026", "Comprehensive guide to Python...", "Balaji", ["Python", "Tutorial"])
p2 = blog.publish_post("Building Web Backends with Django", "Learn MTV architecture...", "Alex", ["Django", "Web"])
p3 = blog.publish_post("Flask REST API Microservices", "Fast and lightweight APIs...", "Balaji", ["Flask", "Python", "API"])
# Query by tag:
print("\n--- ๐ท๏ธ Posts Tagged 'Python' ---")
for p in blog.filter_by_tag("Python"):
print("โข", p)
# Read post:
read_post = blog.get_by_slug("mastering-python-3-in-2026")
print(f"\n๐ Read Post: {read_post.title} | Views: {read_post.views}")
- Automatic slugification of titles for SEO-friendly URLs (
/posts/mastering-python-3-in-2026). - Tag-based multi-category filtering and view counter tracking.
A complete authentication service implementing salted password hashing, credential verification, session management, and login throttling:
# =========================================================================
# PROJECT 2: SECURE USER AUTHENTICATION & SESSION SYSTEM
# =========================================================================
import hashlib
import secrets
import time
class SecureAuthService:
"""Production authentication service with salted hashing & session tokens."""
def __init__(self):
self.user_database = {} # {username: {"salt": salt, "hash": hash, "role": role}}
self.active_sessions = {} # {session_token: {"username": username, "expires": timestamp}}
def _hash_password(self, password, salt):
"""Generates SHA-256 hash combined with random salt."""
return hashlib.sha256((password + salt).encode("utf-8")).hexdigest()
def register_user(self, username, password, role="User"):
if username in self.user_database:
raise ValueError(f"Username '{username}' is already taken!")
salt = secrets.token_hex(16) # Cryptographically secure 32-char hex salt
pw_hash = self._hash_password(password, salt)
self.user_database[username] = {"salt": salt, "hash": pw_hash, "role": role}
print(f"โ
Registered user: {username} [{role}]")
def login(self, username, password):
user_record = self.user_database.get(username)
if not user_record:
print(f"โ Login Failed: User '{username}' does not exist.")
return None
input_hash = self._hash_password(password, user_record["salt"])
if secrets.compare_digest(input_hash, user_record["hash"]):
token = secrets.token_urlsafe(32) # Generate 43-character session token
self.active_sessions[token] = {"username": username, "role": user_record["role"], "login_time": time.time()}
print(f"๐ Login Successful for '{username}'! Session Token: {token[:12]}...")
return token
else:
print(f"โ Login Failed: Invalid password for '{username}'.")
return None
def validate_session(self, token):
session_info = self.active_sessions.get(token)
if session_info:
return True, session_info["username"], session_info["role"]
return False, None, None
# Run Project 2 Demonstration:
auth = SecureAuthService()
auth.register_user("balaji_dev", "SecurePass#2026", role="Admin")
auth.register_user("alex_smith", "SimplePass123", role="User")
# Attempt Login:
token = auth.login("balaji_dev", "SecurePass#2026")
is_valid, user, role = auth.validate_session(token)
print(f"Session Valid: {is_valid} | Authenticated as: {user} ({role})")
secrets.token_hex(16): Generates true random cryptographic salts.secrets.compare_digest(): Prevents timing attacks during hash verification.
A complete task management engine supporting projects, priority levels, status updates, and milestone tracking:
# =========================================================================
# PROJECT 3: COLLABORATIVE TASK & PROJECT MANAGEMENT APP
# =========================================================================
from enum import Enum, auto
class Priority(Enum):
LOW = auto()
MEDIUM = auto()
HIGH = auto()
CRITICAL = auto()
class TaskItem:
def __init__(self, task_id, title, priority=Priority.MEDIUM, assignee="Unassigned"):
self.id = task_id
self.title = title
self.priority = priority
self.assignee = assignee
self.is_completed = False
def mark_complete(self):
self.is_completed = True
def __repr__(self):
status = "โ
Done" if self.is_completed else "โณ In Progress"
return f" โข Task #{self.id}: {self.title:30} [{self.priority.name:8}] Assignee: {self.assignee:12} [{status}]"
class ProjectBoard:
def __init__(self, project_name):
self.name = project_name
self.tasks = []
self._counter = 1
def add_task(self, title, priority=Priority.MEDIUM, assignee="Unassigned"):
task = TaskItem(self._counter, title, priority, assignee)
self.tasks.append(task)
self._counter += 1
return task
def get_progress_summary(self):
total = len(self.tasks)
completed = sum(1 for t in self.tasks if t.is_completed)
pct = (completed / total * 100) if total > 0 else 0
return f"๐ Project '{self.name}': {completed}/{total} Tasks Completed ({pct:.1f}%)"
# Run Project 3 Demonstration:
board = ProjectBoard("Python Masterclass 2026")
t1 = board.add_task("Write Phase 10 Web Development", Priority.CRITICAL, "Balaji")
t2 = board.add_task("Verify Code Examples in IDE", Priority.HIGH, "Alex")
t3 = board.add_task("Deploy Sitemap to Production", Priority.MEDIUM, "Chloe")
t1.mark_complete()
print(board.get_progress_summary())
print("\n--- Current Task Board ---")
for t in board.tasks:
print(t)
Using Priority enums guarantees that priority values cannot be corrupted by typos (like "critcal").
A complete e-commerce domain model featuring product catalogs, cart management, discounts, and inventory validation:
# =========================================================================
# PROJECT 4: ENTERPRISE E-COMMERCE BACKEND ENGINE
# =========================================================================
class ECommerceStore:
def __init__(self):
self.catalog = {
101: {"name": "MacBook Pro M3", "price": 169999.00, "stock": 5},
102: {"name": "Mechanical Keyboard", "price": 2499.00, "stock": 20},
103: {"name": "4K Ultra-Wide Monitor", "price": 34999.00, "stock": 4}
}
self.orders = []
def place_order(self, customer_name, items_dict, coupon_code=None):
"""Processes order atomically: items_dict = {product_id: quantity}"""
print(f"\n--- ๐๏ธ Processing Checkout for '{customer_name}' ---")
# 1. Validate Stock:
subtotal = 0.0
for pid, qty in items_dict.items():
product = self.catalog.get(pid)
if not product:
raise ValueError(f"Product #{pid} does not exist!")
if product["stock"] < qty:
raise ValueError(f"Insufficient stock for '{product['name']}'! Only {product['stock']} available.")
subtotal += product["price"] * qty
# 2. Apply Coupon:
discount = 0.0
if coupon_code == "SUPER2026":
discount = subtotal * 0.10 # 10% discount
print("๐ท๏ธ Coupon 'SUPER2026' applied (-10% Discount)!")
total = subtotal - discount
# 3. Deduct Stock:
for pid, qty in items_dict.items():
self.catalog[pid]["stock"] -= qty
order_record = {
"order_id": len(self.orders) + 1001,
"customer": customer_name,
"items": items_dict,
"total": total
}
self.orders.append(order_record)
print(f"โ
Order #{order_record['order_id']} Confirmed! Total Charged: โน{total:,.2f}")
return order_record
# Run Project 4 Demonstration:
store = ECommerceStore()
store.place_order("Balaji", {101: 1, 102: 2}, coupon_code="SUPER2026")
store.place_order("Alex", {103: 1})
print("\n--- Current Warehouse Inventory ---")
for pid, p in store.catalog.items():
print(f"โข #{pid}: {p['name']:25} | In Stock: {p['stock']} | Price: โน{p['price']:,.2f}")
Validating all stock quantities before deducting ensures orders never fail halfway through checkout.
A complete educational management portal modeling Students, Courses, dynamic Grade calculation, and GPA computation:
# =========================================================================
# PROJECT 5: STUDENT ACADEMIC PORTAL & GRADE TRACKING SYSTEM
# =========================================================================
class StudentPortal:
def __init__(self):
self.students = {} # {student_id: {"name": str, "grades": {course: score}}}
def enroll_student(self, student_id, name):
self.students[student_id] = {"name": name, "grades": {}}
print(f"๐ Enrolled Student #{student_id}: {name}")
def record_grade(self, student_id, course_name, score):
if student_id not in self.students:
raise KeyError(f"Student #{student_id} not found!")
self.students[student_id]["grades"][course_name] = score
def generate_report_card(self, student_id):
student = self.students.get(student_id)
if not student:
return "Student record not found."
grades = student["grades"]
if not grades:
return f"No grades recorded yet for {student['name']}."
avg = sum(grades.values()) / len(grades)
gpa = round((avg / 100) * 10, 2)
report = [
f"========================================",
f"๐ ACADEMIC REPORT: {student['name']} (ID #{student_id})",
f"----------------------------------------"
]
for course, score in grades.items():
letter = "A+" if score >= 90 else ("A" if score >= 80 else ("B" if score >= 70 else "C"))
report.append(f" โข {course:25}: {score}/100 [{letter}]")
report.append(f"----------------------------------------")
report.append(f"Average Score: {avg:.1f}% | GPA: {gpa}/10.0")
report.append(f"========================================")
return "\n".join(report)
# Run Project 5 Demonstration:
portal = StudentPortal()
portal.enroll_student(202601, "Balaji Dev")
portal.record_grade(202601, "Python Programming", 98)
portal.record_grade(202601, "Web Architecture", 94)
portal.record_grade(202601, "Database Systems", 92)
print(portal.generate_report_card(202601))
Calculates weighted GPAs and letter grades dynamically from raw scores.
A complete REST API system with structured JSON responses, validation, and token authentication:
# =========================================================================
# PROJECT 6: PRODUCTION-GRADE REST API SERVICE
# =========================================================================
import json
class RESTAPIService:
"""Production REST API Router & Handler Service."""
def __init__(self):
self.articles = {
1: {"id": 1, "title": "Flask vs Django", "author": "Balaji"},
2: {"id": 2, "title": "SQLAlchemy 2.0 Deep Dive", "author": "Alex"}
}
def dispatch(self, method, path, payload=None, auth_token=None):
"""Unified API Dispatcher."""
# 1. Auth Guard for write operations:
if method in ["POST", "PUT", "DELETE"]:
if auth_token != "secret_token_2026":
return {"status_code": 401, "body": {"error": "Unauthorized: Invalid API Token"}}
# 2. Route Matching:
if method == "GET" and path == "/api/v1/articles":
return {"status_code": 200, "body": list(self.articles.values())}
elif method == "GET" and path.startswith("/api/v1/articles/"):
art_id = int(path.split("/")[-1])
article = self.articles.get(art_id)
if article:
return {"status_code": 200, "body": article}
return {"status_code": 404, "body": {"error": "Article not found"}}
elif method == "POST" and path == "/api/v1/articles":
if not payload or "title" not in payload:
return {"status_code": 400, "body": {"error": "Missing 'title' field"}}
new_id = len(self.articles) + 1
new_art = {"id": new_id, "title": payload["title"], "author": payload.get("author", "Anonymous")}
self.articles[new_id] = new_art
return {"status_code": 201, "body": new_art}
return {"status_code": 404, "body": {"error": "Endpoint not found"}}
# Run Project 6 Demonstration:
api = RESTAPIService()
print("1. GET /api/v1/articles:")
print(json.dumps(api.dispatch("GET", "/api/v1/articles"), indent=2))
print("\n2. Unauthorized POST /api/v1/articles:")
print(json.dumps(api.dispatch("POST", "/api/v1/articles", {"title": "New Post"}, auth_token="invalid"), indent=2))
print("\n3. Authorized POST /api/v1/articles:")
print(json.dumps(api.dispatch("POST", "/api/v1/articles", {"title": "Asyncio in Python 3.12", "author": "Balaji"}, auth_token="secret_token_2026"), indent=2))
Implements HTTP status code compliance (200, 201, 400, 401, 404) and JSON payload formatting.
Creating a new database connection on every single HTTP request will quickly overwhelm your database server under moderate load. Always use a connection pool (like SQLAlchemy QueuePool or PgBouncer for PostgreSQL).
Instantiate the ECommerceStore from Project 4 and place an order for 2 Mechanical Keyboards and 1 MacBook Pro.
store = ECommerceStore()
order = store.place_order("Kavya", {102: 2, 101: 1}, coupon_code="SUPER2026")
print("Order Details:", order)
Q How do I choose between Flask and Django for a new project?
Choose Flask if you are building a small-to-medium microservice, lightweight REST API, or want total freedom over your database and ORM choice. Choose Django if you are building a full-featured web app needing user authentication, database migrations, and an admin dashboard immediately.
Q What is ASGI in modern Python web development?
ASGI (Asynchronous Server Gateway Interface) is the successor to WSGI. It supports async/await concurrency, WebSockets, and long-polling HTTP connections.
Q How should static files be handled in high-traffic production web apps?
In high-scale production apps, static assets (CSS, JS, images, videos) should be offloaded to an Object Storage service (like AWS S3 or Cloudflare R2) fronted by a global Content Delivery Network (CDN).