Creating an advanced-level Training Management System (TMS) with Flask and Bootstrap 5 involves designing a robust database structure, implementing backend logic, and creating responsive frontend pages. Below is a detailed implementation:

Database Structure

The database will be designed using SQLAlchemy (ORM for Flask). Here's the schema:

Tables

  • Users: Stores user information (trainers, trainees, and admins).
  • Trainers: Stores trainer information.
  • Trainees: Stores trainee information.
  • Courses: Stores course details.
  • Sessions: Stores session details.
  • Enrollments: Stores enrollment 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='trainee') # Roles: trainee, trainer, admin
trainer = db.relationship('Trainer', backref='user', uselist=False)
trainee = db.relationship('Trainee', backref='user', uselist=False)
class Trainer(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='trainer', lazy=True)
sessions = db.relationship('Session', backref='trainer', lazy=True)
class Trainee(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)
enrollments = db.relationship('Enrollment', backref='trainee', lazy=True)
payments = db.relationship('Payment', backref='trainee', 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)
trainer_id = db.Column(db.Integer, db.ForeignKey('trainer.id'), nullable=False)
sessions = db.relationship('Session', backref='course', lazy=True)
enrollments = db.relationship('Enrollment', 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)
trainer_id = db.Column(db.Integer, db.ForeignKey('trainer.id'), nullable=False)
session_date = db.Column(db.DateTime, nullable=False)
duration = db.Column(db.Integer, nullable=False) # in minutes
class Enrollment(db.Model):
id = db.Column(db.Integer, primary_key=True)
trainee_id = db.Column(db.Integer, db.ForeignKey('trainee.id'), nullable=False)
course_id = db.Column(db.Integer, db.ForeignKey('course.id'), nullable=False)
enrollment_date = db.Column(db.DateTime, nullable=False)
class Payment(db.Model):
id = db.Column(db.Integer, primary_key=True)
trainee_id = db.Column(db.Integer, db.ForeignKey('trainee.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)

Flask Application Structure

Here’s the directory structure for the project:


training_management_system/

├── app.py
├── models.py
├── forms.py
├── templates/
│ ├── base.html
│ ├── index.html
│ ├── login.html
│ ├── register.html
│ ├── trainer_dashboard.html
│ ├── trainee_dashboard.html
│ ├── admin_dashboard.html
│ ├── create_course.html
│ ├── create_session.html
│ ├── enroll_course.html
│ ├── view_courses.html
│ ├── view_sessions.html
│ ├── view_payments.html
│ └── manage_trainees.html
├── static/
│ ├── css/
│ │ └── styles.css
│ ├── js/
│ │ └── scripts.js
│ └── images/
└── requirements.txt

Flask Application Code


from flask import Flask, render_template, request, redirect, url_for, flash, session
from flask_sqlalchemy import SQLAlchemy
from models import db, User, Trainer, Trainee, Course, Session, Payment, Enrollment
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:///training_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('trainer_dashboard') if user.role == 'trainer' else 'trainee_dashboard' if user.role == 'trainee' else 'admin_dashboard')
flash('Login failed. Check your email and password.', 'danger')
return render_template('login.html', form=form)
@app.route('/trainer_dashboard')
def trainer_dashboard():
if 'user_id' not in session or session['role'] != 'trainer':
return redirect(url_for('login'))
trainer = Trainer.query.filter_by(user_id=session['user_id']).first()
return render_template('trainer_dashboard.html', trainer=trainer)
@app.route('/trainee_dashboard')
def trainee_dashboard():
if 'user_id' not in session or session['role'] != 'trainee':
return redirect(url_for('login'))
trainee = Trainee.query.filter_by(user_id=session['user_id']).first()
return render_template('trainee_dashboard.html', trainee=trainee)
@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'] != 'trainer':
return redirect(url_for('login'))
form = CourseForm()
if form.validate_on_submit():
course = Course(name=form.name.data, description=form.description.data, trainer_id=session['user_id'])
db.session.add(course)
db.session.commit()
flash('Course created successfully!', 'success')
return redirect(url_for('trainer_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'] != 'trainer':
return redirect(url_for('login'))
form = SessionForm()
if form.validate_on_submit():
session_obj = Session(course_id=form.course_id.data, trainer_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('trainer_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'] != 'trainee':
return redirect(url_for('login'))
form = EnrollmentForm()
if form.validate_on_submit():
enrollment = Enrollment(trainee_id=session['user_id'], course_id=form.course_id.data, enrollment_date=datetime.now())
db.session.add(enrollment)
db.session.commit()
flash('Enrolled in course successfully!', 'success')
return redirect(url_for('trainee_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'] != 'trainee':
return redirect(url_for('login'))
payments = Payment.query.filter_by(trainee_id=session['user_id']).all()
return render_template('view_payments.html', payments=payments)
@app.route('/manage_trainees')
def manage_trainees():
if 'user_id' not in session or session['role'] != 'admin':
return redirect(url_for('login'))
trainees = Trainee.query.all()
return render_template('manage_trainees.html', trainees=trainees)
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)

models.py


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='trainee') # Roles: trainee, trainer, admin
trainer = db.relationship('Trainer', backref='user', uselist=False)
trainee = db.relationship('Trainee', backref='user', uselist=False)
class Trainer(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='trainer', lazy=True)
sessions = db.relationship('Session', backref='trainer', lazy=True)
class Trainee(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)
enrollments = db.relationship('Enrollment', backref='trainee', lazy=True)
payments = db.relationship('Payment', backref='trainee', 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)
trainer_id = db.Column(db.Integer, db.ForeignKey('trainer.id'), nullable=False)
sessions = db.relationship('Session', backref='course', lazy=True)
enrollments = db.relationship('Enrollment', 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)
trainer_id = db.Column(db.Integer, db.ForeignKey('trainer.id'), nullable=False)
session_date = db.Column(db.DateTime, nullable=False)
duration = db.Column(db.Integer, nullable=False) # in minutes
class Enrollment(db.Model):
id = db.Column(db.Integer, primary_key=True)
trainee_id = db.Column(db.Integer, db.ForeignKey('trainee.id'), nullable=False)
course_id = db.Column(db.Integer, db.ForeignKey('course.id'), nullable=False)
enrollment_date = db.Column(db.DateTime, nullable=False)
class Payment(db.Model):
id = db.Column(db.Integer, primary_key=True)
trainee_id = db.Column(db.Integer, db.ForeignKey('trainee.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)

forms.py


from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, DateField, SelectField, IntegerField, TextAreaField, SubmitField, DecimalField
from wtforms.validators import DataRequired, Email, Length
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(), Length(min=2, max=50)])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired(), Length(min=6, max=200)])
submit = SubmitField('Register')
class LoginForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
submit = SubmitField('Login')
class CourseForm(FlaskForm):
name = StringField('Course Name', validators=[DataRequired()])
description = TextAreaField('Description', validators=[DataRequired()])
submit = SubmitField('Create Course')
class SessionForm(FlaskForm):
course_id = SelectField('Course', coerce=int, validators=[DataRequired()])
session_date = DateField('Session Date', format='%Y-%m-%d', validators=[DataRequired()])
duration = IntegerField('Duration (in minutes)', validators=[DataRequired()])
submit = SubmitField('Create Session')
class EnrollmentForm(FlaskForm):
course_id = SelectField('Course', coerce=int, validators=[DataRequired()])
submit = SubmitField('Enroll in Course')
class PaymentForm(FlaskForm):
amount = DecimalField('Amount', validators=[DataRequired()])
submit = SubmitField('Make Payment')

HTML Templates

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">
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
<title>{% block title %}Training 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') }}">Training 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'] == 'trainer' %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('trainer_dashboard') }}">Dashboard</a>
</li>
{% elif session['role'] == 'trainee' %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('trainee_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>

templates/index.html


{% extends 'base.html' %}
{% block content %}
<h1>Welcome to the Training Management System</h1>
<p>Enhance your skills with our training 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 %}

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 %}

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 %}

templates/trainer_dashboard.html


{% extends 'base.html' %}
{% block content %}
<h2>Trainer Dashboard</h2>
<p>Welcome, {{ trainer.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 %}

templates/trainee_dashboard.html


{% extends 'base.html' %}
{% block content %}
<h2>Trainee Dashboard</h2>
<p>Welcome, {{ trainee.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 %}

templates/admin_dashboard.html


{% extends 'base.html' %}
{% block content %}
<h2>Admin Dashboard</h2>
<p>Welcome, Admin!</p>
<a href="{{ url_for('manage_trainees') }}" class="btn btn-primary">Manage Trainees</a>
{% endblock %}

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 %}

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 %}

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 %}

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>Trainer</th>
</tr>
</thead>
<tbody>
{% for course in courses %}
<tr>
<td>{{ course.name }}</td>
<td>{{ course.description }}</td>
<td>{{ course.trainer.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

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>Trainer</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.trainer.name }}</td>
<td>{{ session.duration }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

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 %}

templates/manage_trainees.html


{% extends 'base.html' %}
{% block content %}
<h2>Manage Trainees</h2>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
{% for trainee in trainees %}
<tr>
<td>{{ trainee.name }}</td>
<td>{{ trainee.user.email }}</td>
<td>{{ trainee.phone }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

Static Files

static/css/styles.css


body {
background-color: #f8f9fa;
}
.navbar {
margin-bottom: 20px;
}
.table {
margin-top: 20px;
}

JavaScript

static/js/scripts.js


// Custom JavaScript can be added here
document.addEventListener('DOMContentLoaded', function() {
console.log("Training Management System Loaded");
});

Requirements

requirements.txt


Flask==2.0.1
Flask-SQLAlchemy==2.5.1
Flask-WTF==0.15.1
WTForms==2.3.3

This structure provides a comprehensive foundation for an advanced Training Management System using Flask and Bootstrap 5. You can expand upon this by adding features such as notifications, advanced reporting, and user management functionalities.