我写了一个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,并且遇到了同样的问题。几乎所有请求都处理不正确。这可能与比赛条件有关吗?究竟会发生什么?
答案 0 :(得分:0)
You cannot use a global variable like this in Django. A Django application usually runs in multiple server processes which do not share memory. Calling the game
view would only set the global variable current_question_key
in one of the processes. All other processes would still have old values. As a request can be served by any process, you get more or less random results.
The Django development server uses multi-threading instead of multi-processing. Threads, as opposed to processes, share the same memory, so all request see the same value for current_question_key
.
You have to store current_question_key
for each user in a way that is accessible to all processes. The most obvious solution would be to store this information in the user's session:
request.session['current_question_key'] = ...
Alternatively, you could store it in the database, e.g. with ForeignKey
in a customer user model, or if you want to keep track of games any in a separate table like this:
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)
You can then get the current game for a user by sorting by creation date:
Game.objects.filter(user=request.user).order_by('-created_at').first()
Depending on how often the current question changes, you could also consider using a key-value like Redis, although that complicates things a bit.