A complete full-stack teaching example demonstrating client-server architecture, RESTful API design, and functional programming principles using vanilla JavaScript and Flask.
This project demonstrates:
- Backend: Python Flask REST API with SQLite database
- Frontend: Vanilla JavaScript (ES6+) with functional programming patterns
- Architecture: Clean separation of concerns following KISS principle
- Security: SQL injection prevention via parameterized queries
- Design Pattern: Revealing Module Pattern for JavaScript organization
student-management-API_c6e/
├── backend.py # Flask API server (RESTful endpoints)
├── init_db.py # Database initialization script
├── database.db # SQLite database (created after init)
├── index.html # Frontend interface
├── app.js # Vanilla JavaScript (functional approach)
├── style.css # Minimal CSS styling
├── CLAUDE.md # Complete teaching documentation
└── README.md # This file
- CRUD Operations: Create, Read, Update, Delete students
- Real-time Statistics: Average grades, distribution, min/max
- Grade Filtering: Filter students by minimum grade
- Grade Categories: Color-coded grades (A/B/C/Failing)
- Form Validation: Client and server-side validation
- Error Handling: Proper HTTP status codes and user feedback
- Responsive Design: Clean, modern interface
- Backend: Python 3, Flask, Flask-CORS, SQLite3
- Frontend: HTML5, CSS3, Vanilla JavaScript (ES6+)
- API: RESTful architecture with JSON
- Database: SQLite with parameterized queries
- Python 3.x installed
- pip (Python package manager)
- Modern web browser
pip install flask flask-corspython3 init_db.pyThis creates database.db and populates it with 5 sample students:
- Alice Johnson (92)
- Bob Smith (78)
- Charlie Brown (85)
- Diana Prince (95)
- Eve Adams (88)
python3 backend.pyThe Flask API server will start on http://127.0.0.1:5000
You should see:
* Serving Flask app 'backend'
* Debug mode: on
* Running on http://127.0.0.1:5000
IMPORTANT: You need to run a separate HTTP server for the frontend!
Option A: Serve with Python HTTP server (recommended)
# In a NEW terminal window (keep backend running in the first)
python3 -m http.server 8000Then open your browser to: http://localhost:8000
Option B: Open directly
xdg-open index.html
# or simply open index.html in your browserNote: This may cause CORS issues with some browsers.
WRONG: Opening http://127.0.0.1:5000 in your browser
- Result: 404 Error - "The requested URL was not found on the server"
- Why: The Flask backend is an API-only server with no HTML routes
CORRECT: This is a TWO-SERVER architecture:
-
Backend API Server (Port 5000) - Serves JSON data only
Terminal 1: python3 backend.py Routes: /api/students, /api/statistics, etc. DO NOT access http://localhost:5000 in browser! -
Frontend HTTP Server (Port 8000) - Serves HTML/CSS/JS files
Terminal 2: python3 -m http.server 8000 Access: http://localhost:8000 ← Use this URL!
How it works:
Browser → localhost:8000 → index.html loads
↓
app.js makes fetch() calls
↓
localhost:5000/api/*
↓
Flask returns JSON
Testing the API directly (for development):
# Use curl, not your browser
curl http://localhost:5000/api/students
curl http://localhost:5000/api/statistics- View Students: The main page displays all students with their grades
- Add Student: Click "Add Student" button, fill the form, submit
- Edit Student: Click "Edit" on any student card
- Delete Student: Click "Delete" (with confirmation)
- Filter by Grade: Use the "Min Grade" input to filter students
- View Statistics: See real-time grade statistics at the top
Base URL: http://localhost:5000/api
GET /api/students
curl http://localhost:5000/api/studentsGET /api/students?min_grade=90
curl http://localhost:5000/api/students?min_grade=90GET /api/students/<id>
curl http://localhost:5000/api/students/1POST /api/students
curl -X POST http://localhost:5000/api/students \
-H "Content-Type: application/json" \
-d '{"name":"John Doe","email":"john@school.edu","grade":87}'PUT /api/students/<id>
curl -X PUT http://localhost:5000/api/students/1 \
-H "Content-Type: application/json" \
-d '{"name":"Alice Johnson","email":"alice@school.edu","grade":95}'DELETE /api/students/<id>
curl -X DELETE http://localhost:5000/api/students/1GET /api/statistics
curl http://localhost:5000/api/statisticsResponse example:
{
"total_students": 5,
"average_grade": 87.6,
"highest_grade": 95,
"lowest_grade": 78,
"a_students": 2,
"b_students": 2,
"c_students": 1,
"failing_students": 0
}CREATE TABLE students (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
grade INTEGER CHECK(grade >= 0 AND grade <= 100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);- SQL Injection Prevention: Parameterized queries (
?placeholders) - Input Validation: Server-side validation before database operations
- CORS Handling: Controlled cross-origin requests
- Error Handling: Proper HTTP status codes (400, 404, 201)
- Pure Functions: API helper functions without side effects
- Higher-Order Functions:
validate_jsondecorator pattern - Function Composition: Building complex operations from simple functions
- Immutability: Not modifying data directly
- Single Responsibility: Each function does one thing
- Minimal Dependencies: Only Flask and built-in libraries
- Clear Naming: Self-documenting code
- No Over-Engineering: SQLite instead of complex ORMs
- Revealing Module Pattern: JavaScript app organization
- Decorator Pattern: Input validation in Flask
- MVC-like Separation: Routes, data layer, presentation separate
Symptom: Opening http://127.0.0.1:5000 shows 404 error
Cause: You're accessing the API backend directly. It only serves JSON at /api/* routes.
Solution:
- Keep backend running (Terminal 1:
python3 backend.py) - Start frontend server (Terminal 2:
python3 -m http.server 8000) - Open browser to
http://localhost:8000(NOT port 5000!)
See the "
# Find and kill the process using port 5000
lsof -i :5000
kill -9 <PID>
# Or use a different port in backend.py
app.run(debug=True, port=5001)Make sure Flask-CORS is installed and the backend is running. The CORS(app) line in backend.py enables cross-origin requests.
If you get "database is locked" errors:
rm database.db
python3 init_db.py- Check backend is running:
curl http://localhost:5000/api/students - Check browser console for errors (F12)
- Verify API_BASE URL in app.js matches your backend
rm database.db
python3 init_db.pysqlite3 database.db "SELECT * FROM students;"In backend.py, change:
app.run(debug=True, port=5000) # Development
app.run(debug=False, port=5000) # Production-like- Add Search: Implement name/email search functionality
- Pagination: Handle large student lists with pages
- Export CSV: Add endpoint to export data as CSV
- Authentication: Implement simple token-based auth
- Sorting: Add sorting by name, grade, date
- Bulk Operations: Delete or update multiple students
- Grade History: Track grade changes over time
- Input Sanitization: Add additional validation rules
Educational project - Free to use and modify for teaching purposes.
Teaching example following KISS principle and Unix philosophy. Created for Computer Science education.
This repository has multiple versions for different learning levels:
- Description: Complete web application with Flask REST API + Vanilla JavaScript frontend
- Technologies: Flask, SQLite, HTML/CSS/JS
- Architecture: Client-Server (2 servers: backend API + frontend)
- Best for: Learning full-stack development, RESTful APIs, client-server architecture
- Description: Command-line only version using native Python + SQLite
- Technologies: Python 3 standard library, SQLite
- Architecture: Simple CLI application
- Best for: Learning database basics, CRUD operations, Python programming
- See: README_MVP.md for details
Switch branches:
# View full-stack version
git checkout main
# View basic MVP version
git checkout python+sqliteCurrent Status:
- Backend API Server: Running on http://127.0.0.1:5000
- Database: Initialized with 5 sample students
- Ready to use!