
本文详解如何修复在线学习系统中测验成绩被覆盖的问题,通过读取用户历史成绩、合并新得分并持久化存储,实现跨模块的累计成绩展示。
本文详解如何修复在线学习系统中测验成绩被覆盖的问题,通过读取用户历史成绩、合并新得分并持久化存储,实现跨模块的累计成绩展示。
在当前代码中,submit_quiz() 视图每次执行时都会初始化一个全新的 scores 字典(全部设为 0),然后仅计算本次所答模块的得分,再直接覆写 users_data.txt 中该用户的全部三项成绩字段。这导致用户此前在其他模块获得的分数被清零——例如模块2提交后,“Fundamentals of Networking”得分被重置为 0,而非保留模块1已取得的 10 分。
要实现“各模块成绩累加、全局可见”的效果,核心在于:读取用户原有成绩 → 仅更新本次作答模块的分数 → 保留其余模块历史成绩 → 整体写回。
以下是关键修复步骤与优化后的代码逻辑:
✅ 步骤一:读取并解析用户历史成绩(在 submit_quiz() 开头)
# 读取现有用户数据,定位当前用户并提取其历史成绩
users_data_file = open("users_data.txt", "r")
users = users_data_file.read().splitlines()
users_data_file.close()
# 初始化为默认值(若用户首次答题)
current_scores = {
'Fundamentals of Networking': 0,
'Network Tools and Testing Devices': 0,
'Network Cables': 0
}
# 查找并加载该用户的历史成绩
for user_line in users:
if email == get_field(user_line, 1):
current_scores['Fundamentals of Networking'] = int(get_field(user_line, 3))
current_scores['Network Tools and Testing Devices'] = int(get_field(user_line, 4))
current_scores['Network Cables'] = int(get_field(user_line, 5))
break✅ 步骤二:动态识别当前作答模块,并仅更新对应项
# 在遍历 quiz_files 的循环内(即处理某一份试卷时):
for idx, quiz_file in enumerate(quiz_files):
# ... 加载题目、收集答案、计算本模块得分(score_this_quiz) ...
# 动态映射文件名到模块名
quiz_name_map = {
"questions1.txt": "Fundamentals of Networking",
"questions2.txt": "Network Tools and Testing Devices",
"questions3.txt": "Network Cables"
}
quiz_name = quiz_name_map.get(quiz_file, "")
# ✅ 关键:只更新本次模块的成绩,其余保持原值
if quiz_name in current_scores:
# 注意:此处应使用 score_this_quiz(你代码中已计算出的单模块得分)
# 示例:假设你已在循环内统计出本模块正确数 → let's call it `correct_count`
current_scores[quiz_name] = correct_count # ← 覆盖(非累加)该模块最新成绩⚠️ 注意:是否“累加”还是“覆盖”取决于业务逻辑。根据你的示例(模块2提交后,“Fundamentals…”仍显示10分),说明你希望保留历史最高分或最新有效分,而非简单累加。因此这里采用「覆盖本模块最新成绩」更符合需求。
✅ 步骤三:安全写回用户数据(推荐 with 语句)
# 更新 users 列表中该用户的行
for i, user_line in enumerate(users):
if email == get_field(user_line, 1):
users[i] = ",".join([
get_field(user_line, 0), # ID
get_field(user_line, 1), # email
get_field(user_line, 2), # other field
str(current_scores['Fundamentals of Networking']),
str(current_scores['Network Tools and Testing Devices']),
str(current_scores['Network Cables'])
])
break
# ✅ 推荐:使用 with 自动管理文件资源
with open("users_data.txt", "w") as f:
f.write("\n".join(users))✅ 补充建议
- 避免全局变量 email 和 quiz_attempts:改用 Flask 的 session 存储用户标识,提升并发安全性;
- 结构化数据存储:长期来看,建议迁移到 SQLite 或 JSON 文件,避免手动解析 CSV 字段;
- 结果页 results() 无需改动:它已正确从 users_data.txt 读取全部三项成绩,只需确保 submit_quiz() 写入正确即可。
修复后,无论用户完成模块1、模块2或模块3,其个人成绩面板(result.html)将始终显示三项课程的最新有效得分,真正实现“一次提交,全局可见”。

















