はじめに
この記事では、FlaskとHTMLを使用してシンプルなクイズアプリを作成する方法を紹介します。このアプリケーションでは、サーバーサイドでFlaskを利用して問題を生成し、クライアントサイドではHTMLとJavaScriptを使って問題を表示し、ユーザーからの回答を受け付けます。クイズの問題は算数の基本的な計算問題をランダムに生成し、ユーザーが選択肢をクリックして回答できるインターフェースを提供します。さらに、ユーザーがクイズを提出すると、正答率を計算して結果を表示します。
このアプリを作成することで、Flaskの基本的な使い方や、HTML、CSS、JavaScriptの連携方法を学ぶことができます。以下に、ディレクトリ構成やプログラムの詳細な説明を示しますので、ぜひ参考にしてみてください。
ディレクトリ構成
まず、アプリケーションのディレクトリ構成は以下のようになります。
quiz_app/
├── app.py
├── static/
│ └── style.css
└── templates/
└── index.html
-
app.py
: Flaskアプリケーションのメインファイル -
static/style.css
: アプリケーションのスタイルを定義するCSSファイル -
templates/index.html
: アプリケーションのHTMLテンプレートファイル
プログラムの説明
app.py
Flaskを使ってサーバーサイドのロジックを処理します。
from flask import Flask, render_template, request, jsonify, session
import random
app = Flask(__name__)
app.secret_key = 'your_secret_key' # セッションを使用するために必要
def generate_math_question():
operators = ['+', '-', '*']
num1 = random.randint(1, 10)
num2 = random.randint(1, 10)
operator = random.choice(operators)
question = f"{num1} {operator} {num2}"
answer = eval(question)
# 正解を含む4つの選択肢を生成
options = [answer,
random.randint(answer - 10, answer + 10),
random.randint(answer - 10, answer + 10),
random.randint(answer - 10, answer + 10)]
random.shuffle(options)
return {
"question": f"What is {question}?",
"options": options,
"answer": answer
}
@app.route('/')
def index():
return render_template('index.html')
@app.route('/get_question', methods=['POST'])
def get_question():
quiz = [generate_math_question() for _ in range(10)] # 10問ランダムに生成
session['questions'] = quiz # セッションに質問を保存
return jsonify(quiz)
@app.route('/submit_answers', methods=['POST'])
def submit_answers():
user_answers = request.json.get('answers', [])
questions = session.get('questions', [])
if not questions:
return jsonify({'error': 'No questions found in session'}), 400
score = 0
for user_answer, question in zip(user_answers, questions):
if user_answer is not None and int(user_answer) == question['answer']:
score += 1
percentage = (score / len(questions)) * 100
return jsonify({'score': percentage})
if __name__ == '__main__':
app.run(debug=True)
-
generate_math_question()
: ランダムな数学の問題を生成し、正解と選択肢を含む辞書を返します。 -
/
(ルート):index.html
テンプレートをレンダリングして返します。 -
/get_question
: クイズの10問を生成し、セッションに保存してJSON形式で返します。 -
/submit_answers
: ユーザーが送信した回答をセッションに保存された質問と比較し、正解率を計算して返します。
templates/index.html
HTMLファイルで、フロントエンドのUIを提供します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quiz App</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<h1>Quiz App</h1>
<div id="quiz-container"></div>
<button onclick="submitQuiz()">Submit Quiz</button>
<div id="result"></div>
<script>
let questions = [];
let userAnswers = [];
window.onload = async function() {
const response = await fetch('/get_question', { method: 'POST' });
questions = await response.json();
displayQuiz();
};
function displayQuiz() {
const container = document.getElementById('quiz-container');
container.innerHTML = '';
questions.forEach((q, index) => {
const questionDiv = document.createElement('div');
questionDiv.classList.add('question');
questionDiv.innerHTML = `<p>${q.question}</p>`;
q.options.forEach(option => {
const optionButton = document.createElement('button');
optionButton.textContent = option;
optionButton.classList.add('option-button');
optionButton.onclick = () => selectAnswer(index, option, optionButton);
questionDiv.appendChild(optionButton);
});
container.appendChild(questionDiv);
});
}
function selectAnswer(questionIndex, answer, button) {
userAnswers[questionIndex] = answer;
// 選択されたボタンのスタイルを変更
const questionDiv = button.parentElement;
const optionButtons = questionDiv.getElementsByClassName('option-button');
for (let btn of optionButtons) {
btn.classList.remove('selected');
}
button.classList.add('selected');
}
async function submitQuiz() {
const response = await fetch('/submit_answers', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ answers: userAnswers })
});
const result = await response.json();
if (result.error) {
document.getElementById('result').textContent = result.error;
} else {
document.getElementById('result').textContent = `Your score: ${result.score}%`;
}
}
</script>
</body>
</html>
-
window.onload
: ページが読み込まれたときにサーバーから問題を取得し、表示します。 -
displayQuiz()
: 取得した問題をHTMLに表示します。 -
selectAnswer()
: ユーザーが選択肢をクリックしたときの処理を行い、選択された回答を記録します。 -
submitQuiz()
: ユーザーの回答をサーバーに送信し、結果を表示します。
static/style.css
アプリケーションのスタイルを定義します。
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
margin: 0;
padding: 0;
}
h1 {
text-align: center;
margin-top: 20px;
}
#quiz-container {
display: flex;
flex-direction: column;
align-items: center;
margin: 20px;
}
.question {
margin-bottom: 20px;
}
.option-button {
display: block;
margin: 5px 0;
padding: 10px;
background-color: #ffffff;
border: 1px solid #cccccc;
border-radius: 5px;
cursor: pointer;
}
.option-button.selected {
background-color: #d3ffd3;
}
button {
display: block;
margin: 20px auto;
padding: 10px 20px;
font-size: 16px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
#result {
text-align: center;
font-size: 18px;
font-weight: bold;
}
- スタイルの設定で、ボタンのデザインやページ全体の見た目を整えています。
実行
以下のコマンドで Flask アプリケーションを実行します。
python app.py
ブラウザで http://127.0.0.1:5000/
にアクセスすると以下の画面が出ます
おわりに
この記事では、FlaskとHTMLを使ったシンプルなクイズアプリの作成方法を説明しました。サーバーサイドで問題を生成し、クライアントサイドでユーザーインターフェースを構築することで、Webアプリケーションの基本的なフローを学ぶことができたかと思います。
このクイズアプリをもとに、さらに複雑な機能を追加することもできます。例えば、ユーザー認証機能や問題の難易度選択、ユーザーごとの成績管理などの機能を追加して、自分だけのオリジナルアプリを作成してみてください。
質問やコメントがあれば、お気軽にお知らせください。最後までお読みいただき、ありがとうございました。