django - Django 应用程序在部署时出现问题。比赛条件?
问题描述
我编写了一个用于测验的 django 应用程序,它会检查用户的答案并在用户提交答案后立即更新分数。这是执行此操作的相应视图 -
current_question_key = 0 #This is a global variable.
def check_answer(request):
current_user = request.user
current_team = Team.objects.get(user = current_user)
current_score = current_team.score
if request.method == "POST":
answer = request.POST.get('answer')
question = Question.objects.get(id = current_question_key)
if answer == question.answer:
if question in current_team.questions_answered.all(): #This is required to prevent the score from increasing if the somebody submits a correct answer to the same question more than once
pass
else:
current_team.score = current_score + question.score_increment
current_team.questions_answered.add(question)
current_team.save()
else:
# This is required to prevent the score from decreasing if someone has answered it correctly earlier
if question in current_team.questions_answered.all():
pass
else :
current_team.score = current_score - question.score_increment//negative_marking_factor
current_team.save()
return HttpResponse(status=204) #This means that the server has successfully processed the request and is not going to return any data.
else:
return HttpResponse("Error404")
current_question_key 的值从用于将问题发送到前端的视图更改 -
def game(request):
if request.method == "POST":
key = request.POST.get('questionKey')
global current_question_key
current_question_key = key
question = Question.objects.get(id = key)
question_text = question.question_text
data = {
'question_text':question_text
}
return JsonResponse(data)
else:
current_user = request.user
current_team = Team.objects.get(user = current_user)
score = current_team.score
name = current_user.username
return render(request, 'Base/main.html', {'teamname':name, 'score':score})
在 django 的开发服务器上进行测试时,即使大约 10 人同时使用它,它也能正常工作。但是,一旦我尝试使用 nginx(托管在我的笔记本电脑上,同时有 5 个用户)来提供它,该应用程序就完全失控了,甚至正确的答案也被评估为错误的。
我也尝试过 apache 并且遇到了同样的问题。几乎所有的请求都被错误地处理了。这可能与比赛条件有关吗?这里到底发生了什么?
解决方案
你不能在 Django 中使用这样的全局变量。一个 Django 应用程序通常运行在多个不共享内存的服务器进程中。调用game
视图只会current_question_key
在其中一个进程中设置全局变量。所有其他进程仍将具有旧值。由于任何进程都可以处理请求,因此您或多或少会得到随机结果。
Django 开发服务器使用多线程而不是多处理。与进程相反,线程共享相同的内存,因此所有请求都看到相同的current_question_key
.
您必须current_question_key
以所有进程都可以访问的方式为每个用户存储。最明显的解决方案是将此信息存储在用户的会话中:
request.session['current_question_key'] = ...
或者,您可以将其存储在数据库中,例如ForeignKey
在客户用户模型中,或者如果您想在单独的表中跟踪游戏,如下所示:
from django.contrib.auth import get_user_model
from django.db import models
class Game(model.Model)
user = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE
)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
然后,您可以通过按创建日期排序来获取用户的当前游戏:
Game.objects.filter(user=request.user).order_by('-created_at').first()
根据当前问题更改的频率,您还可以考虑使用像 Redis 这样的键值对,尽管这会使事情变得有点复杂。
推荐阅读
- ios - 如何像 Swift 中的 Uber 共享一样在 GoogleMap 中绘制曲线形状折线?
- abap - FORM 和 PERFORM 中的参数数量不同
- r - How plot new point in ggplot with older color data?
- android - Algolia 和 Firestore 价格 + 评论
- python - pandas plot 聚合时间戳索引
- nginx - 如何使用 metricbeat 检查我的服务器是否还活着,这可能吗?
- angularjs - ng-repeat : 添加新元素的 ng-model 问题
- swift - 如果存在多个有效的登录用户,则无法调用 RealmSwift currentUser
- asp.net-core - 发送客户端请求后如何执行操作?
- r - 根据上年和今年汇总