基于Django的在线测验应用多用户访问隔离及并发处理咨询
问题根源与解决方案
核心问题
你现在的测验进度(当前第几题)肯定是存在全局变量里了,所有用户的请求都会读写这个变量,自然会互相干扰。这和用runserver、Apache还是Docker无关——部署方式不解决用户状态隔离的逻辑问题。
正确的用户状态隔离方案
1. 使用Django Session存储临时测验状态
这是Web开发处理用户专属临时数据的标准做法,完全符合最佳实践。Django的Session默认存在数据库中,每个用户有唯一的sessionid(通过Cookie传递),状态完全隔离。
示例代码思路:
- 用户开始测验时,初始化Session:
def start_quiz(request): request.session['current_question'] = 1 request.session['quiz_id'] = 1 # 若存在多个测验 # 其他初始化逻辑 return render(request, 'quiz.html') - 用户答题后,更新Session中的进度:
def submit_answer(request): current_q = request.session.get('current_question', 1) # 验证答案逻辑 request.session['current_question'] = current_q + 1 # 返回下一题数据 return JsonResponse({'next_question': current_q + 1}) - 每次加载题目时,从Session读取当前进度:
def get_current_question(request): current_q = request.session.get('current_question', 1) question = Question.objects.get(id=current_q) return JsonResponse({'question': question.text})
2. 结合用户账号存储持久化进度(若有登录系统)
如果你的应用要求用户登录,建议把测验进度存在数据库的关联表中,这样用户即使关闭浏览器重新登录,也能继续之前的测验。
示例模型设计:
from django.db import models from django.contrib.auth.models import User class QuizProgress(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) quiz_id = models.IntegerField() current_question = models.IntegerField(default=1) completed = models.BooleanField(default=False)
每次用户操作时,更新这个表的记录即可,完全隔离每个用户的进度。
3. 前端本地存储(补充方案)
如果不需要后端跟踪进度,也可以把当前题存在前端的localStorage里,前端自己管理进度,提交答案时再传给后端。但这种方式不适合需要防作弊的场景,因为用户可以手动修改localStorage的值。
纠正你的错误思路
- 为每个用户启动新线程:完全没必要。Web服务器本身就是多线程/多进程处理请求,每个请求都是独立的,问题出在你共享了全局状态,和线程无关。
- 部署到Apache或Docker:这些只是部署环境,解决的是服务的运行和扩展问题,不解决用户状态隔离的核心问题——哪怕换了部署方式,全局变量还是会被所有用户共享。
内容的提问来源于stack exchange,提问作者Thomas Langer
相关产品推荐
相关产品推荐

