Django全局变量问题:测验网站保存用户答案时出现500错误
问题根源与解决方案
为什么会出现name new_user_answer is not defined?
- 全局变量不适合Web请求场景:HTTP请求是无状态且独立的,
global new_user_answer仅在单个请求的进程内有效,后续答题请求无法读取到之前请求设置的全局变量,服务器多进程/多实例部署时这个问题会更频繁。 - ID生成逻辑存在并发风险:用
Answers.objects.all().count() +1生成ID会导致多用户同时创建记录时拿到相同ID值,不仅会引发主键冲突,还会进一步导致变量混乱。
修复方案:用Session存储答题记录ID(推荐)
1. 重构初始化答题记录的函数
去掉全局变量,改用数据库自增主键,并将生成的记录ID存入用户Session:
def start_quiz(request): user = request.user user_group = user.groups.values_list() university = user_group[0][1] # 数据库id字段设置为自增主键,无需手动生成ID new_line = Answers(id_user=user) new_line.save() # 将新记录ID存入Session,用于后续答题请求 request.session['current_answer_id'] = new_line.id return redirect('/1')
2. 修改保存答案的函数
从Session中读取当前答题记录ID,同时增加异常处理避免报错:
def save_answer(request, id_questions): # 从Session获取当前答题记录ID current_answer_id = request.session.get('current_answer_id') if not current_answer_id: # 无有效记录时跳转到测验开始页 return redirect('/start') try: # 同时校验用户归属,防止越权访问 data = Answers.objects.get(id=current_answer_id, id_user=request.user) except Answers.DoesNotExist: # 记录不存在或不属于当前用户,跳转回开始页 return redirect('/start') question = # 替换为实际的题名字段 answers = # 替换为用户提交的答案数据 setattr(data, question, answers) data.save() if int(id_questions) < 47: return redirect(f'/{int(id_questions) +1 }') else: # 测验完成后清除Session中的记录ID del request.session['current_answer_id'] return render(request, 'index.html')
额外优化:Session丢失后的兼容处理
如果用户Session意外失效,可以通过用户关联查询最新的答题记录:
def save_answer(request, id_questions): current_answer_id = request.session.get('current_answer_id') if not current_answer_id: # 查找当前用户最新的答题记录(假设未完成的记录没有结束标识) latest_answer = Answers.objects.filter(id_user=request.user).order_by('-id').first() if latest_answer: current_answer_id = latest_answer.id request.session['current_answer_id'] = current_answer_id else: return redirect('/start') # 后续逻辑同上述代码...
内容的提问来源于stack exchange,提问作者LeonidPetrovich
相关产品推荐
相关产品推荐

