Creating an advanced-level Online Quiz Platform involves designing a robust database structure, implementing backend logic, and creating responsive frontend pages using Flask and Bootstrap 5. Below is a detailed breakdown of the database structure, Flask application code, and related pages.

Database Structure

The database will store information about users, quizzes, questions, answers, and results. We'll use SQLAlchemy (ORM for Flask) to define the 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)
quizzes = db.relationship('Quiz', backref='user', lazy=True)
results = db.relationship('Result', backref='user', lazy=True)
class Quiz(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
questions = db.relationship('Question', backref='quiz', lazy=True)
class Question(db.Model):
id = db.Column(db.Integer, primary_key=True)
quiz_id = db.Column(db.Integer, db.ForeignKey('quiz.id'), nullable=False)
question_text = db.Column(db.Text, nullable=False)
answers = db.relationship('Answer', backref='question', lazy=True)
class Answer(db.Model):
id = db.Column(db.Integer, primary_key=True)
question_id = db.Column(db.Integer, db.ForeignKey('question.id'), nullable=False)
answer_text = db.Column(db.Text, nullable=False)
is_correct = db.Column(db.Boolean, default=False)
class Result(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
quiz_id = db.Column(db.Integer, db.ForeignKey('quiz.id'), nullable=False)
score = db.Column(db.Integer, nullable=False)
timestamp = db.Column(db.DateTime, default=datetime.utcnow)

Flask Application Structure

Here’s the directory structure for the project:


online_quiz_platform/

├── app/
│ ├── __init__.py # Initialize the Flask app and database
│ ├── models.py # Database models (User , Quiz, Question, Answer, Result)
│ ├── routes.py # Application routes and views
│ ├── forms.py # Forms for user input (if using Flask-WTF)
│ ├── static/ # Static files (CSS, JS, images)
│ │ ├── css/
│ │ │ └── styles.css # Custom CSS styles
│ │ └── js/
│ │ └── scripts.js # Custom JavaScript files
│ └── templates/ # HTML templates
│ ├── base.html # Base layout for templates
│ ├── index.html # Home page
│ ├── login.html # Login page
│ ├── register.html # Registration page
│ ├── dashboard.html # User dashboard
│ ├── quiz_details.html # Quiz details page
│ ├── take_quiz.html # Take quiz page
│ └── payment.html # Payment page (if applicable)

├── migrations/ # Database migration files (if using Flask-Migrate)

├── config.py # Configuration settings for the app

├── requirements.txt # Python package dependencies

└── run.py # Entry point to run the application

Flask Application Code

Below is the Flask application code with routes, forms, and database integration.


from flask import Flask, render_template, request, redirect, url_for, flash, session
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///online_quiz.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
# User Registration
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
email = request.form['email']
password = generate_password_hash(request.form['password'], method='sha256')
new_user = User(username=username, email=email, password=password)
db.session.add(new_user)
db.session.commit()
flash('Registration successful! Please log in.', 'success')
return redirect(url_for('login'))
return render_template('register.html')
# User Login
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form['email']
password = request.form['password']
user = User.query.filter_by(email=email).first()
if user and check_password_hash(user.password, password):
session['user_id'] = user.id
session['username'] = user.username
flash('Login successful!', 'success')
return redirect(url_for('dashboard'))
else:
flash('Invalid email or password.', 'danger')
return render_template('login.html')
# Dashboard
@app.route('/')
def dashboard():
if 'user_id' not in session:
return redirect(url_for('login'))
quizzes = Quiz.query.all()
return render_template('dashboard.html', quizzes=quizzes)
# Create Quiz
@app.route('/create_quiz', methods=['POST'])
def create_quiz():
title = request.form.get('title')
description = request.form.get('description')
new_quiz = Quiz(title=title, description=description, user_id=session['user_id'])
db.session.add(new_quiz)
db.session.commit()
flash('Quiz created successfully!', 'success')
return redirect(url_for('dashboard'))
# Quiz Details
@app.route('/quiz/<int:id>')
def quiz_details(id):
quiz = Quiz.query.get_or_404(id)
questions = Question.query.filter_by(quiz_id=id).all()
return render_template('quiz_details.html', quiz=quiz, questions=questions)
# Create Question
@app.route('/create_question/<int:quiz_id>', methods=['POST'])
def create_question(quiz_id):
question_text = request.form.get('question_text')
new_question = Question(question_text=question_text, quiz_id=quiz_id)
db.session.add(new_question)
db.session.commit()
flash('Question added successfully!', 'success')
return redirect(url_for('quiz_details', id=quiz_id))
# Create Answer
@app.route('/create_answer/<int:question_id>', methods=['POST'])
def create_answer(question_id):
answer_text = request.form.get('answer_text')
is_correct = request.form.get('is_correct') == 'on'
new_answer = Answer(answer_text=answer_text, question_id=question_id, is_correct=is_correct)
db.session.add(new_answer)
db.session.commit()
flash('Answer added successfully!', 'success')
return redirect(url_for('quiz_details', id=question_id))
# Take Quiz
@app.route('/take_quiz/<int:id>', methods=['GET', 'POST'])
def take_quiz(id):
quiz = Quiz.query.get_or_404(id)
questions = Question.query.filter_by(quiz_id=id).all()
if request.method == 'POST':
score = 0
for question in questions:
selected_answer = request.form.get(str(question.id))
if selected_answer:
answer = Answer.query.get(selected_answer)
if answer and answer.is_correct:
score += 1
result = Result(user_id=session['user_id'], quiz_id=id, score=score)
db.session.add(result)
db.session.commit()
flash(f'You scored {score} out of {len(questions)}!', 'success')
return redirect(url_for('dashboard'))
return render_template('take_quiz.html', quiz=quiz, questions=questions)
# User Logout
@app.route('/logout')
def logout():
session.pop('user_id', None)
session.pop('username', None)
flash('You have been logged out.', 'success')
return redirect(url_for('dashboard'))
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)

HTML Templates

Here are some basic HTML templates using Bootstrap 5 for the pages mentioned.

register.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>Register</title>
</head>
<body>
<div class="container">
<h2 class="mt-5">Register</h2>
<form method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

login.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>Login</title>
</head>
<body>
<div class="container">
<h2 class="mt-5">Login</h2>
<form method="POST">
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

dashboard.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>Dashboard</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Online Quiz Platform</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/logout">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h2>Your Quizzes</h2>
<form action="/create_quiz" method="POST">
<div class="mb-3">
<label for="title" class="form-label">Quiz Title</label>
<input type="text" class="form-control" id="title" name="title" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control" id="description" name="description" rows="3" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Create Quiz</button>
</form>
<hr>
<h3>All Quizzes</h3>
<div class="row">
{% for quiz in quizzes %}
<div class="col-md-4">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title">{{ quiz.title }}</h5>
<p class="card-text">{{ quiz.description }}</p>
<a href="{{ url_for('quiz_details', id=quiz.id) }}" class="btn btn-info">View Quiz</a>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

quiz_details.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>{{ quiz.title }}</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Online Quiz Platform</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/logout">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h2>{{ quiz.title }}</h2>
<p>{{ quiz.description }}</p>
<h4>Questions</h4>
<form action="/create_question/{{ quiz.id }}" method="POST">
<div class="mb-3">
<label for="question_text" class="form-label">Question Text</label>
<input type="text" class="form-control" id="question_text" name="question_text" required>
</div>
<button type="submit" class="btn btn-primary">Add Question</button>
</form>
<hr>
<h4>Existing Questions</h4>
<ul class="list-group">
{% for question in questions %}
<li class="list-group-item">
{{ question.question_text }}
<form action="/create_answer/{{ question.id }}" method="POST" class="mt-2">
<div class="mb-3">
<label for="answer_text" class="form-label">Answer Text</label>
<input type="text" class="form-control" id="answer_text" name="answer_text" required>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="is_correct" name="is_correct">
<label class="form-check-label" for="is_correct">Correct Answer</label>
</div>
<button type="submit" class="btn btn-primary mt-2">Add Answer</button>
</div>
</form>
</li>
{% endfor %}
</ul>
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary mt-3">Back to Dashboard</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

take_quiz.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>Take Quiz: {{ quiz.title }}</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">Online Quiz Platform</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/logout">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h2>{{ quiz.title }}</h2>
<form method="POST">
{% for question in questions %}
<div class="mb-3">
<label class="form-label">{{ question.question_text }}</label>
<div>
{% for answer in question.answers %}
<div class="form-check">
<input class="form-check-input" type="radio" name="{{ question.id }}" id="answer{{ answer.id }}" value="{{ answer.id }}">
<label class="form-check-label" for="answer{{ answer.id }}">{{ answer.answer_text }}</label>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit Quiz</button>
</form>
<a href="{{ url_for('dashboard') }}" class="btn btn-secondary mt-3">Back to Dashboard</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Additional Features and Enhancements

To further enhance the Online Quiz Platform, consider implementing the following features:

  • User Profiles: Allow users to create and edit their profiles, including profile pictures and bios.
  • Quiz Editing and Deletion: Implement functionality for users to edit or delete their quizzes and questions.
  • Leaderboard: Create a leaderboard to display top scores for each quiz.
  • Timed Quizzes: Add a timer for quizzes to increase the challenge.
  • Quiz Categories: Implement categories for quizzes to help users find quizzes of interest.
  • Email Notifications: Set up email notifications for users when new quizzes are created or when they achieve high scores.
  • Analytics Dashboard: Provide analytics for users to see their performance over time, including scores and completion rates.
  • Mobile Responsiveness: Ensure that the platform is fully responsive and works well on mobile devices.

Conclusion

This advanced Online Quiz Platform structure provides a comprehensive foundation for building a fully functional application using Flask and Bootstrap 5. You can further enhance the application by integrating user profiles, quiz editing features, and a leaderboard. The modular design allows for easy expansion and maintenance, making it suitable for both beginners and experienced developers.