Creating an advanced-level Coaching Management System (CMS) with Flask and Bootstrap 5 involves designing a robust database structure, implementing backend logic, and creating responsive frontend pages. Below is a detailed implementation:
1. Database Structure
The database will be designed using SQLAlchemy (ORM for Flask). Here's the schema:
Tables
- Users: Stores user information (coaches, students, and admins).
- Coaches: Stores coach information.
- Students: Stores student information.
- Courses: Stores course details.
- Sessions: Stores session details.
- Payments: Stores payment details.
Database Models
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
db = SQLAlchemy()
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), unique=True, nullable=False)
email = db.Column(db.String(100), unique=True, nullable=False)
password = db.Column(db.String(200), nullable=False)
role = db.Column(db.String(20), default='student') # Roles: student, coach, admin
coach = db.relationship('Coach', backref='user', uselist=False)
student = db.relationship('Student', backref='user', uselist=False)
class Coach(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
name = db.Column(db.String(100), nullable=False)
specialization = db.Column(db.String(100), nullable=False)
courses = db.relationship('Course', backref='coach', lazy=True)
sessions = db.relationship('Session', backref='coach', lazy=True)
class Student(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
name = db.Column(db.String(100), nullable=False)
dob = db.Column(db.Date, nullable=False)
gender = db.Column(db.String(10), nullable=False)
phone = db.Column(db.String(15), nullable=False)
courses = db.relationship('Course', secondary='enrollment', backref='students', lazy=True)
sessions = db.relationship('Session', secondary='attendance', backref='students', lazy=True)
class Course(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text, nullable=False)
coach_id = db.Column(db.Integer, db.ForeignKey('coach.id'), nullable=False)
sessions = db.relationship('Session', backref='course', lazy=True)
class Session(db.Model):
id = db.Column(db.Integer, primary_key=True)
course_id = db.Column(db.Integer, db.ForeignKey('course.id'), nullable=False)
coach_id = db.Column(db.Integer, db.ForeignKey('coach.id'), nullable=False)
session_date = db.Column(db.DateTime, nullable=False)
duration = db.Column(db.Integer, nullable=False) # in minutes
class Enrollment(db.Model):
student_id = db.Column(db.Integer, db.ForeignKey('student.id'), primary_key=True)
course_id = db.Column(db.Integer, db.ForeignKey('course.id'), primary_key=True)
class Attendance(db.Model):
student_id = db.Column(db.Integer, db.ForeignKey('student.id'), primary_key=True)
session_id = db.Column(db.Integer, db.ForeignKey('session.id'), primary_key=True)
attended = db.Column(db.Boolean, default=False)
class Payment(db.Model):
id = db.Column(db.Integer, primary_key=True)
student_id = db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False)
course_id = db.Column(db.Integer, db.ForeignKey('course.id'), nullable=False)
payment_date = db.Column(db.DateTime, nullable=False)
amount = db.Column(db.Float, nullable=False)
2. Flask Application Structure
Here’s the directory structure for the project:
coaching_management_system/
│
├── app.py
├── models.py
├── forms.py
├── templates/
│ ├── base.html
│ ├── index.html
│ ├── login.html
│ ├── register.html
│ ├── coach_dashboard.html
│ ├── student_dashboard.html
│ ├── admin_dashboard.html
│ ├── create_course.html
│ ├── create_session.html
│ ├── enroll_course.html
│ ├── view_courses.html
│ ├── view_sessions.html
│ ├── view_payments.html
│ └── manage_students.html
├── static/
│ ├── css/
│ │ └── styles.css
│ ├── js/
│ │ └── scripts.js
│ └── images/
└── requirements.txt
3. Flask Application Code
app.py
from flask import Flask, render_template, request, redirect, url_for, flash, session
from flask_sqlalchemy import SQLAlchemy
from models import db, User, Coach, Student, Course, Session, Payment
from forms import LoginForm, RegistrationForm, CourseForm, SessionForm, EnrollmentForm
from datetime import datetime
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///coaching_management.db'
db.init_app(app)
# Routes
@app.route('/')
def index():
return render_template('index.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
if form.validate_on_submit():
user = User(username=form.username.data, email=form.email.data, password=form.password.data)
db.session.add(user)
db.session.commit()
flash('Registration successful! Please login.', 'success')
return redirect(url_for('login'))
return render_template('register.html', form=form)
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user and user.password == form.password.data: # Use hashed passwords in production
session['user_id'] = user.id
session['role'] = user.role
flash('Login successful!', 'success')
return redirect(url_for('coach_dashboard') if user.role == 'coach' else 'student_dashboard' if user.role == 'student' else 'admin_dashboard')
flash('Login failed. Check your email and password.', 'danger')
return render_template('login.html', form=form)
@app.route('/coach_dashboard')
def coach_dashboard():
if 'user_id' not in session or session['role'] != 'coach':
return redirect(url_for('login'))
coach = Coach.query.filter_by(user_id=session['user_id']).first()
return render_template('coach_dashboard.html', coach=coach)
@app.route('/student_dashboard')
def student_dashboard():
if 'user_id' not in session or session['role'] != 'student':
return redirect(url_for('login'))
student = Student.query.filter_by(user_id=session['user_id']).first()
return render_template('student_dashboard.html', student=student)
@app.route('/admin_dashboard')
def admin_dashboard():
if 'user_id' not in session or session['role'] != 'admin':
return redirect(url_for('login'))
return render_template('admin_dashboard.html')
@app.route('/create_course', methods=['GET', 'POST'])
def create_course():
if 'user_id' not in session or session['role'] != 'coach':
return redirect(url_for('login'))
form = CourseForm()
if form.validate_on_submit():
course = Course(name=form.name.data, description=form.description.data, coach_id=session['user_id'])
db.session.add(course)
db.session.commit()
flash('Course created successfully!', 'success')
return redirect(url_for('coach_dashboard'))
return render_template('create_course.html', form=form)
@app.route('/create_session', methods=['GET', 'POST'])
def create_session():
if 'user_id' not in session or session['role'] != 'coach':
return redirect(url_for('login'))
form = SessionForm()
if form.validate_on_submit():
session_obj = Session(course_id=form.course_id.data, coach_id=session['user_id'], session_date=form.session_date.data, duration=form.duration.data)
db.session.add(session_obj)
db.session.commit()
flash('Session created successfully!', 'success')
return redirect(url_for('coach_dashboard'))
return render_template('create_session.html', form=form)
@app.route('/enroll_course', methods=['GET', 'POST'])
def enroll_course():
if 'user_id' not in session or session['role'] != 'student':
return redirect(url_for('login'))
form = EnrollmentForm()
if form.validate_on_submit():
enrollment = Enrollment(student_id=session['user_id'], course_id=form.course_id.data)
db.session.add(enrollment)
db.session.commit()
flash('Enrolled in course successfully!', 'success')
return redirect(url_for('student_dashboard'))
return render_template('enroll_course.html', form=form)
@app.route('/view_courses')
def view_courses():
if 'user_id' not in session:
return redirect(url_for('login'))
courses = Course.query.all()
return render_template('view_courses.html', courses=courses)
@app.route('/view_sessions')
def view_sessions():
if 'user_id' not in session:
return redirect(url_for('login'))
sessions = Session.query.all()
return render_template('view_sessions.html', sessions=sessions)
@app.route('/view_payments')
def view_payments():
if 'user_id' not in session or session['role'] != 'student':
return redirect(url_for('login'))
payments = Payment.query.filter_by(student_id=session['user_id']).all()
return render_template('view_payments.html', payments=payments)
@app.route('/manage_students')
def manage_students():
if 'user_id' not in session or session['role'] != 'admin':
return redirect(url_for('login'))
students = Student.query.all()
return render_template('manage_students.html', students=students)
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)
5. HTML Templates
1. templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>{% block title %}Coaching Management System{% endblock %}</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('index') }}">Coaching Management</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
{% if 'user_id' in session %}
{% if session['role'] == 'coach' %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('coach_dashboard') }}">Dashboard</a>
</li>
{% elif session['role'] == 'student' %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('student_dashboard') }}">Dashboard</a>
</li>
{% elif session['role'] == 'admin' %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('admin_dashboard') }}">Dashboard</a>
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('logout') }}">Logout</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('login') }}">Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('register') }}">Register</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
<div class="container mt-4">
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert alert-info">
{% for message in messages %}
{{ message }}<br>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
2. templates/index.html
{% extends 'base.html' %}
{% block content %}
<h1>Welcome to the Coaching Management System</h1>
<p>Enhance your skills with our coaching programs!</p>
<a href="{{ url_for('register') }}" class="btn btn-primary">Register</a>
<a href="{{ url_for('login') }}" class="btn btn-secondary">Login</a>
{% endblock %}
3. templates/login.html
{% extends 'base.html' %}
{% block content %}
<h2>Login</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.email.label(class="form-label") }}
{{ form.email(class="form-control") }}
</div>
<div class="mb-3">
{{ form.password.label(class="form-label") }}
{{ form.password(class="form-control") }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
{% endblock %}
4. templates/register.html
{% extends 'base.html' %}
{% block content %}
<h2>Register</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.username.label(class="form-label") }}
{{ form.username(class="form-control") }}
</div>
<div class="mb-3">
{{ form.email.label(class="form-label") }}
{{ form.email(class="form-control") }}
</div>
<div class="mb-3">
{{ form.password.label(class="form-label") }}
{{ form.password(class="form-control") }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
{% endblock %}
5. templates/coach_dashboard.html
{% extends 'base.html' %}
{% block content %}
<h2>Coach Dashboard</h2>
<p>Welcome, {{ coach.name }}!</p>
<a href="{{ url_for('create_course') }}" class="btn btn-primary">Create Course</a>
<a href="{{ url_for('create_session') }}" class="btn btn-secondary">Create Session</a>
<a href="{{ url_for('view_sessions') }}" class="btn btn-info">View Sessions</a>
{% endblock %}
6. templates/student_dashboard.html
{% extends 'base.html' %}
{% block content %}
<h2>Student Dashboard</h2>
<p>Welcome, {{ student.name }}!</p>
<a href="{{ url_for('enroll_course') }}" class="btn btn-primary">Enroll in Course</a>
<a href="{{ url_for('view_courses') }}" class="btn btn-secondary">View Courses</a>
<a href="{{ url_for('view_payments') }}" class="btn btn-info">View Payments</a>
{% endblock %}
7. templates/admin_dashboard.html
{% extends 'base.html' %}
{% block content %}
<h2>Admin Dashboard</h2>
<p>Welcome, Admin!</p>
<a href="{{ url_for('manage_students') }}" class="btn btn-primary">Manage Students</a>
{% endblock %}
8. templates/create_course.html
{% extends 'base.html' %}
{% block content %}
<h2>Create Course</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.name.label(class="form-label") }}
{{ form.name(class="form-control") }}
</div>
<div class="mb-3">
{{ form.description.label(class="form-label") }}
{{ form.description(class="form-control") }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
{% endblock %}
9. templates/create_session.html
{% extends 'base.html' %}
{% block content %}
<h2>Create Session</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.course_id.label(class="form-label") }}
{{ form.course_id(class="form-control") }}
</div>
<div class="mb-3">
{{ form.session_date.label(class="form-label") }}
{{ form.session_date(class="form-control") }}
</div>
<div class="mb-3">
{{ form.duration.label(class="form-label") }}
{{ form.duration(class="form-control") }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
{% endblock %}
10. templates/enroll_course.html
{% extends 'base.html' %}
{% block content %}
<h2>Enroll in Course</h2>
<form method="POST">
{{ form.hidden_tag() }}
<div class="mb-3">
{{ form.course_id.label(class="form-label") }}
{{ form.course_id(class="form-control") }}
</div>
{{ form.submit(class="btn btn-primary") }}
</form>
{% endblock %}
11. templates/view_courses.html
{% extends 'base.html' %}
{% block content %}
<h2>Available Courses</h2>
<table class="table">
<thead>
<tr>
<th>Course Name</th>
<th>Description</th>
<th>Coach</th>
</tr>
</thead>
<tbody>
{% for course in courses %}
<tr>
<td>{{ course.name }}</td>
<td>{{ course.description }}</td>
<td>{{ course.coach.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
12. templates/view_sessions.html
{% extends 'base.html' %}
{% block content %}
<h2>Upcoming Sessions</h2>
<table class="table">
<thead>
<tr>
<th>Session Date</th>
<th>Course</th>
<th>Coach</th>
<th>Duration (minutes)</th>
</tr>
</thead>
<tbody>
{% for session in sessions %}
<tr>
<td>{{ session.session_date }}</td>
<td>{{ session.course.name }}</td>
<td>{{ session.coach.name }}</td>
<td>{{ session.duration }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
13. templates/view_payments.html
{% extends 'base.html' %}
{% block content %}
<h2>Your Payments </h2>
<table class="table">
<thead>
<tr>
<th>Payment Date</th>
<th>Course</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
{% for payment in payments %}
<tr>
<td>{{ payment.payment_date }}</td>
<td>{{ payment.course.name }}</td>
<td>{{ payment.amount }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
14. templates/manage_students.html
{% extends 'base.html' %}
{% block content %}
<h2>Manage Students</h2>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
{% for student in students %}
<tr>
<td>{{ student.name }}</td>
<td>{{ student.user.email }}</td>
<td>{{ student.phone }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
6. Static Files
1. static/css/styles.css
body {
background-color: #f8f9fa;
}
.navbar {
margin-bottom: 20px;
}
.table {
margin-top: 20px;
}
2. static/js/scripts.js
// Custom JavaScript can be added here
document.addEventListener('DOMContentLoaded', function() {
console.log("Coaching Management System Loaded");
});
7. Requirements
Flask==2.0.1
Flask-SQLAlchemy==2.5.1
Flask-WTF==0.15.1
WTForms==2.3.3
Conclusion
This structure provides a comprehensive foundation for an advanced Coaching Management System using Flask and Bootstrap 5. You can expand upon this by adding features such as notifications, advanced reporting, and user management functionalities.