下面是一个与前面不同的综合示例,展示如何使用 Python + Flask + HTML + CSS + JavaScript + jQuery + Bootstrap + SQLAlchemy 开发一个简单的 在线考试系统。教师可以创建考试,学生可以参加考试并查看成绩。
1. 项目结构
online_exam/
│
├── app.py # Flask 应用主文件
├── models.py # SQLAlchemy 模型定义
├── requirements.txt # 依赖文件
├── static/ # 静态文件(CSS, JS, 图片等)
│ ├── css/
│ │ └── styles.css # 自定义 CSS
│ └── js/
│ └── scripts.js # 自定义 JavaScript
│
├── templates/ # HTML 模板文件
│ ├── base.html # 基础模板
│ ├── index.html # 主页模板
│ ├── create_exam.html # 创建考试模板
│ ├── exams.html # 考试列表模板
│ ├── take_exam.html # 参加考试模板
│ ├── results.html # 考试成绩模板
│ └── view_results.html # 查看成绩模板
│
└── database.db # SQLite 数据库文件
2. 安装依赖
在项目根目录下创建 requirements.txt
文件,内容如下:
Flask==2.3.2
Flask-SQLAlchemy==3.0.5
Bootstrap==5.3.0
jQuery==3.6.0
安装依赖:
pip install -r requirements.txt
3. Flask 应用 (app.py
)
from flask import Flask, render_template, request, redirect, url_for, flash
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db' # SQLite 数据库
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'your_secret_key' # 用于消息闪现的密钥
db = SQLAlchemy(app)
# 考试模型
class Exam(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
questions = db.relationship('Question', backref='exam', lazy=True)
results = db.relationship('Result', backref='exam', lazy=True)
# 问题模型
class Question(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.Text, nullable=False)
option1 = db.Column(db.String(100), nullable=False)
option2 = db.Column(db.String(100), nullable=False)
option3 = db.Column(db.String(100), nullable=False)
option4 = db.Column(db.String(100), nullable=False)
correct_option = db.Column(db.String(100), nullable=False)
exam_id = db.Column(db.Integer, db.ForeignKey('exam.id'), nullable=False)
# 成绩模型
class Result(db.Model):
id = db.Column(db.Integer, primary_key=True)
student_name = db.Column(db.String(100), nullable=False)
score = db.Column(db.Integer, nullable=False)
exam_id = db.Column(db.Integer, db.ForeignKey('exam.id'), nullable=False)
# 主页路由
@app.route('/')
def index():
return render_template('index.html')
# 创建考试路由
@app.route('/create_exam', methods=['GET', 'POST'])
def create_exam():
if request.method == 'POST':
title = request.form['title']
new_exam = Exam(title=title)
db.session.add(new_exam)
db.session.commit()
flash('考试创建成功!', 'success')
return redirect(url_for('exams'))
return render_template('create_exam.html'))
# 考试列表路由
@app.route('/exams')
def exams():
exams = Exam.query.all()
return render_template('exams.html', exams=exams)
# 参加考试路由
@app.route('/take_exam/<int:id>', methods=['GET', 'POST'])
def take_exam(id):
exam = Exam.query.get_or_404(id)
if request.method == 'POST':
student_name = request.form['student_name']
score = 0
for question in exam.questions:
selected_option = request.form.get(f'question_{question.id}')
if selected_option == question.correct_option:
score += 1
new_result = Result(student_name=student_name, score=score, exam=exam)
db.session.add(new_result)
db.session.commit()
flash('考试提交成功!', 'success')
return redirect(url_for('results', id=exam.id))
return render_template('take_exam.html', exam=exam)
# 考试成绩路由
@app.route('/results/<int:id>')
def results(id):
exam = Exam.query.get_or_404(id)
return render_template('results.html', exam=exam)
# 查看成绩路由
@app.route('/view_results')
def view_results():
results = Result.query.all()
return render_template('view_results.html', results=results)
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)
4. HTML 模板
基础模板 (templates/base.html
)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>在线考试系统</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="{{ url_for('index') }}">在线考试系统</a>
<div class="navbar-nav">
<a class="nav-link" href="{{ url_for('create_exam') }}">创建考试</a>
<a class="nav-link" href="{{ url_for('exams') }}">考试列表</a>
<a class="nav-link" href="{{ url_for('view_results') }}">查看成绩</a>
</div>
</div>
</nav>
<div class="container mt-4">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="{{ url_for('static', filename='js/scripts.js') }}"></script>
</body>
</html>
主页模板 (templates/index.html
)
{% extends 'base.html' %}
{% block content %}
<h1>欢迎来到在线考试系统!</h1>
<p>创建考试或参加考试。</p>
<a href="{{ url_for('create_exam') }}" class="btn btn-primary">创建考试</a>
<a href="{{ url_for('exams') }}" class="btn btn-secondary">查看考试列表</a>
{% endblock %}
创建考试模板 (templates/create_exam.html
)
{% extends 'base.html' %}
{% block content %}
<h1>创建考试</h1>
<form method="POST">
<div class="mb-3">
<label for="title" class="form-label">考试标题</label>
<input type="text" class="form-control" id="title" name="title" required>
</div>
<button type="submit" class="btn btn-primary">创建</button>
</form>
{% endblock %}
考试列表模板 (templates/exams.html
)
{% extends 'base.html' %}
{% block content %}
<h1>考试列表</h1>
<ul class="list-group">
{% for exam in exams %}
<li class="list-group-item">
<h5>{{ exam.title }}</h5>
<a href="{{ url_for('take_exam', id=exam.id) }}" class="btn btn-primary btn-sm">参加考试</a>
</li>
{% endfor %}
</ul>
{% endblock %}
参加考试模板 (templates/take_exam.html
)
{% extends 'base.html' %}
{% block content %}
<h1>{{ exam.title }}</h1>
<form method="POST">
<div class="mb-3">
<label for="student_name" class="form-label">学生姓名</label>
<input type="text" class="form-control" id="student_name" name="student_name" required>
</div>
{% for question in exam.questions %}
<div class="mb-3">
<p>{{ question.content }}</p>
<div class="form-check">
<input class="form-check-input" type="radio" name="question_{{ question.id }}" id="option1_{{ question.id }}" value="option1" required>
<label class="form-check-label" for="option1_{{ question.id }}">{{ question.option1 }}</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="question_{{ question.id }}" id="option2_{{ question.id }}" value="option2" required>
<label class="form-check-label" for="option2_{{ question.id }}">{{ question.option2 }}</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="question_{{ question.id }}" id="option3_{{ question.id }}" value="option3" required>
<label class="form-check-label" for="option3_{{ question.id }}">{{ question.option3 }}</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="question_{{ question.id }}" id="option4_{{ question.id }}" value="option4" required>
<label class="form-check-label" for="option4_{{ question.id }}">{{ question.option4 }}</label>
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">提交</button>
</form>
{% endblock %}
考试成绩模板 (templates/results.html
)
{% extends 'base.html' %}
{% block content %}
<h1>{{ exam.title }} 考试成绩</h1>
<p>您的成绩: {{ exam.results[-1].score }} 分</p>
<a href="{{ url_for('exams') }}" class="btn btn-primary">返回考试列表</a>
{% endblock %}
查看成绩模板 (templates/view_results.html
)
{% extends 'base.html' %}
{% block content %}
<h1>考试成绩</h1>
<ul class="list-group">
{% for result in results %}
<li class="list-group-item">
<h5>{{ result.student_name }}</h5>
<p>考试: {{ result.exam.title }}</p>
<p>成绩: {{ result.score }} 分</p>
</li>
{% endfor %}
</ul>
<a href="{{ url_for('exams') }}" class="btn btn-primary mt-3">返回考试列表</a>
{% endblock %}
5. 静态文件
CSS (static/css/styles.css
)
body {
padding: 20px;
}
h1 {
color: #333;
}
JavaScript (static/js/scripts.js
)
$(document).ready(function() {
console.log("Online Exam System is ready!");
});
6. 运行应用
在项目根目录下运行:
python app.py
访问 http://127.0.0.1:5000/
即可看到在线考试系统。
7. 功能说明
- 创建考试:教师可以创建考试并添加问题。
- 参加考试:学生可以参加考试并提交答案。
- 查看成绩:学生可以查看自己的考试成绩,教师可以查看所有学生的成绩。
8. 扩展功能
- 添加用户认证系统,区分教师和学生。
- 增加考试时间限制和自动评分功能。
- 使用 AJAX 实现无刷新提交考试和查看成绩。
希望这个示例对你有帮助!如果有任何问题,欢迎随时提问!