Introduction
Hey there, aspiring web developers! Ever wanted to create your own web application but felt overwhelmed by complex tools and frameworks? Well, you’re in luck! Today, we’re going to build a fun and interactive quiz app using Flask, a super lightweight and beginner-friendly web framework for Python.
A web framework is like a toolkit that provides a structure and common tools to help you build web applications more efficiently. Instead of writing everything from scratch, a framework gives you a head start! Flask is popular because it’s simple to get started with, yet powerful enough for many types of projects.
By the end of this guide, you’ll have a working quiz app and a solid understanding of Flask’s basic concepts. Ready to dive in? Let’s go!
What You’ll Need
Before we start coding, make sure you have a few things ready:
- Python: Make sure Python 3 is installed on your computer. You can download it from the official Python website.
- A Text Editor: Any text editor will do! Popular choices include VS Code, Sublime Text, or Atom.
- Basic Python Knowledge: You should be familiar with basic Python concepts like variables, lists, dictionaries, and functions.
- A Web Browser: To test your app, of course!
Setting Up Your Environment
First things first, let’s set up a clean workspace for our project. It’s good practice to use a virtual environment.
A virtual environment is like a separate, isolated space on your computer for each Python project. This prevents different projects from interfering with each other’s Python packages (libraries) and versions.
-
Create a Project Folder:
Let’s make a new folder for our quiz app. You can call itflask_quiz_app.bash
mkdir flask_quiz_app
cd flask_quiz_app -
Create a Virtual Environment:
Inside your project folder, run these commands to create and activate a virtual environment:bash
python3 -m venv venv
This command creates a folder namedvenvinside your project directory, which contains a fresh, isolated Python installation. -
Activate the Virtual Environment:
Now, you need to “activate” this environment. The command depends on your operating system:- On macOS/Linux:
bash
source venv/bin/activate - On Windows (Command Prompt):
bash
venv\Scripts\activate.bat - On Windows (PowerShell):
bash
venv\Scripts\Activate.ps1
You’ll know it’s active when you see(venv)at the beginning of your terminal prompt.
- On macOS/Linux:
-
Install Flask:
With your virtual environment active, install Flask usingpip(Python’s package installer):bash
pip install Flask
This command downloads and installs Flask and its dependencies into your isolated virtual environment.
Understanding the Basics of Flask
Before we build the full quiz, let’s look at a super simple Flask app. This will help you understand the core components.
Create a file named app.py in your flask_quiz_app folder:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return "Hello, Quiz Builder! This is our first Flask app."
if __name__ == '__main__':
# app.run(debug=True) starts the development server.
# debug=True means that if you make changes to your code, the server will restart automatically,
# and you'll get helpful error messages in your browser.
app.run(debug=True)
To run this app, save app.py and, with your virtual environment activated, open your terminal in the flask_quiz_app directory and type:
python app.py
You should see output similar to this:
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Open your web browser and go to http://127.0.0.1:5000/. You should see “Hello, Quiz Builder! This is our first Flask app.” Congratulations, you just ran your first Flask app!
Designing Our Quiz Structure
For our quiz, we’ll need a way to store questions, their options, and the correct answer. A list of Python dictionaries is perfect for this. Each dictionary will represent one question.
Let’s add this to our app.py file (you can replace or add this above the app = Flask(__name__) line).
quiz_questions = [
{
"id": 0,
"question": "What is the capital of France?",
"options": ["Berlin", "Madrid", "Paris", "Rome"],
"answer": "Paris"
},
{
"id": 1,
"question": "Which planet is known as the Red Planet?",
"options": ["Earth", "Mars", "Jupiter", "Venus"],
"answer": "Mars"
},
{
"id": 2,
"question": "What is 7 times 8?",
"options": ["54", "56", "64", "49"],
"answer": "56"
},
{
"id": 3,
"question": "What is the largest ocean on Earth?",
"options": ["Atlantic", "Indian", "Arctic", "Pacific"],
"answer": "Pacific"
},
{
"id": 4,
"question": "How many continents are there?",
"options": ["5", "6", "7", "8"],
"answer": "7"
}
]
Creating Our Templates (HTML Files)
Web applications typically separate Python logic from the user interface (what the user sees). Flask uses Jinja2 for templating, which allows us to write HTML files with special placeholders to insert dynamic content (like question text or scores).
First, create a new folder named templates inside your flask_quiz_app directory. Flask automatically looks for HTML files in this folder.
mkdir templates
Now, create three HTML files inside the templates folder:
-
index.html(Start Page)
This will be the welcome page with a button to start the quiz.html
<!-- templates/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flask Quiz App</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
.container { max-width: 600px; margin: auto; padding: 20px; border: 1px solid #ddd; border-radius: 8px; }
button { padding: 10px 20px; font-size: 16px; cursor: pointer; background-color: #007bff; color: white; border: none; border-radius: 5px; }
button:hover { background-color: #0056b3; }
</style>
</head>
<body>
<div class="container">
<h1>Welcome to the Flask Quiz!</h1>
<p>Test your knowledge with our fun quiz.</p>
<a href="/question/0"><button>Start Quiz</button></a>
</div>
</body>
</html> -
question.html(Quiz Question Page)
This page will display each question and its options. We’ll use a form for users to submit their answers.html
<!-- templates/question.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Question {{ question_number }}</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
.container { max-width: 600px; margin: auto; padding: 20px; border: 1px solid #ddd; border-radius: 8px; }
h2 { color: #333; }
form { text-align: left; margin-top: 20px; }
label { display: block; margin-bottom: 10px; font-size: 18px; }
input[type="radio"] { margin-right: 10px; }
button { padding: 10px 20px; font-size: 16px; cursor: pointer; background-color: #28a745; color: white; border: none; border-radius: 5px; margin-top: 20px; }
button:hover { background-color: #218838; }
.question-counter { margin-bottom: 20px; color: #666; }
</style>
</head>
<body>
<div class="container">
<p class="question-counter">Question {{ question_number }} of {{ total_questions }}</p>
<h2>{{ question.question }}</h2>
<form action="/submit_answer" method="POST">
<!-- Jinja2 loop: we iterate over the 'options' list from our question data -->
{% for option in question.options %}
<label>
<input type="radio" name="answer" value="{{ option }}" required>
{{ option }}
</label><br>
{% endfor %}
<input type="hidden" name="question_id" value="{{ question.id }}">
<button type="submit">Submit Answer</button>
</form>
</div>
</body>
</html>
Notice the{{ ... }}and{% ... %}. These are Jinja2’s special syntax:
*{{ variable }}: This prints the value of a variable.
*{% for item in list %}and{% endfor %}: This creates a loop, similar to Python’sforloop, to generate multiple HTML elements (like our radio buttons). -
result.html(Results Page)
This page will show the user’s final score.html
<!-- templates/result.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quiz Results</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; margin-top: 50px; }
.container { max-width: 600px; margin: auto; padding: 20px; border: 1px solid #ddd; border-radius: 8px; }
h1 { color: #333; }
p { font-size: 20px; }
.score { font-size: 2.5em; color: #007bff; font-weight: bold; margin: 20px 0; }
a { text-decoration: none; }
button { padding: 10px 20px; font-size: 16px; cursor: pointer; background-color: #6c757d; color: white; border: none; border-radius: 5px; }
button:hover { background-color: #5a6268; }
</style>
</head>
<body>
<div class="container">
<h1>Quiz Finished!</h1>
<p>Your final score is:</p>
<p class="score">{{ score }} / {{ total }}</p>
<a href="/"><button>Play Again</button></a>
</div>
</body>
</html>
Building the Flask Application (app.py)
Now let’s put all the pieces together in our app.py file. We’ll need to modify it significantly from our simple “Hello World” app.
Delete the previous content of app.py (except for quiz_questions if you already added it) and replace it with the following:
from flask import Flask, render_template, request, redirect, url_for, session
app = Flask(__name__)
app.secret_key = 'super_secret_quiz_key_12345'
quiz_questions = [
{
"id": 0,
"question": "What is the capital of France?",
"options": ["Berlin", "Madrid", "Paris", "Rome"],
"answer": "Paris"
},
{
"id": 1,
"question": "Which planet is known as the Red Planet?",
"options": ["Earth", "Mars", "Jupiter", "Venus"],
"answer": "Mars"
},
{
"id": 2,
"question": "What is 7 times 8?",
"options": ["54", "56", "64", "49"],
"answer": "56"
},
{
"id": 3,
"question": "What is the largest ocean on Earth?",
"options": ["Atlantic", "Indian", "Arctic", "Pacific"],
"answer": "Pacific"
},
{
"id": 4,
"question": "How many continents are there?",
"options": ["5", "6", "7", "8"],
"answer": "7"
}
]
@app.route('/')
def index():
# 'session' is a special Flask object to store data specific to a user's browser session.
# We reset the score and current question ID when a user starts or restarts the quiz.
session['score'] = 0
session['current_question_id'] = 0
# 'render_template' tells Flask to send an HTML file to the browser.
# It automatically looks in the 'templates' folder.
return render_template('index.html')
@app.route('/question/<int:question_id>', methods=['GET'])
def show_question(question_id):
# Check if the requested question_id is valid and within our quiz_questions list.
if 0 <= question_id < len(quiz_questions):
question_data = quiz_questions[question_id]
return render_template('question.html',
question=question_data,
question_number=question_id + 1,
total_questions=len(quiz_questions))
else:
# If the question_id is out of bounds, it means the quiz is over,
# or an invalid question was requested. Redirect to results.
return redirect(url_for('results'))
@app.route('/submit_answer', methods=['POST'])
def submit_answer():
# Get the current question ID from the session to find the correct question.
question_id = session.get('current_question_id')
# 'request.form.get('answer')' retrieves the value of the radio button
# named 'answer' from the submitted HTML form.
user_answer = request.form.get('answer')
# Basic validation: If no question ID or answer is found, redirect to the start.
if question_id is None or user_answer is None:
return redirect(url_for('index'))
current_question = quiz_questions[question_id]
# Check if the user's answer is correct.
if user_answer == current_question['answer']:
session['score'] += 1 # Increment the score in the session.
session['current_question_id'] += 1 # Move to the next question.
# Check if there are more questions to display.
if session['current_question_id'] < len(quiz_questions):
# If yes, redirect to the next question. 'url_for' helps generate the correct URL.
return redirect(url_for('show_question', question_id=session['current_question_id']))
else:
# If no more questions, redirect to the results page.
return redirect(url_for('results'))
@app.route('/results')
def results():
final_score = session.get('score', 0) # Get the final score from the session.
total_questions = len(quiz_questions)
# It's good practice to clear session data related to the quiz once it's over,
# so it doesn't carry over to a new session or cause unexpected behavior.
session.pop('score', None)
session.pop('current_question_id', None)
return render_template('result.html', score=final_score, total=total_questions)
if __name__ == '__main__':
app.run(debug=True)
Running Your Quiz App
You’re almost there! With app.py and your templates folder ready, it’s time to run your complete quiz application.
- Save all your files. Make sure
app.pyis in your mainflask_quiz_appfolder, and the three HTML files are inside thetemplatessubfolder. - Ensure your virtual environment is active. If you closed your terminal, navigate back to
flask_quiz_appand reactivate it (e.g.,source venv/bin/activateon macOS/Linux). -
Run the Flask app:
bash
python app.py -
Open your browser and go to
http://127.0.0.1:5000/.
You should now see your quiz app’s welcome page! Click “Start Quiz,” answer the questions, and see your score at the end.
Next Steps and Enhancements
Congratulations on building your first Flask quiz app! This is just the beginning. Here are some ideas to enhance your creation:
- Add more questions: Expand your
quiz_questionslist. - Implement feedback: Show users if their answer was correct or incorrect after each question.
- Styling with CSS: Make your app look much prettier by adding external CSS files. Flask can serve static files (like CSS, JavaScript, images) from a
staticfolder. - Randomize questions: Shuffle the
quiz_questionslist before the quiz starts. - Timer: Add a timer for each question or for the whole quiz.
- User accounts: For a more advanced project, integrate a database to store user scores and allow multiple users.
Conclusion
You’ve just built a simple, yet fully functional, web quiz application using Flask! You’ve learned about setting up a Flask project, managing routes, rendering HTML templates with dynamic data, handling form submissions, and using sessions to keep track of user-specific information.
Flask’s simplicity makes it an excellent choice for learning web development, and this project provides a solid foundation. Keep experimenting, keep building, and have fun exploring the world of web development!
Leave a Reply
You must be logged in to post a comment.