#python #python-3.x #django #django-models #django-views
#python #python-3.x #django #django-модели #django-просмотры
Вопрос:
Я создаю приложение для викторины на Django и борюсь с подсчетом очков.
Это настройка моей модели:
class Quiz(models.Model):
song = models.ForeignKey(Song, null=True, on_delete=models.CASCADE)
title = models.CharField(max_length=15)
slug = models.SlugField(unique=True, max_length=250)
questions_count = models.IntegerField(default=0)
class Question(models.Model):
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
label = models.CharField(max_length=1000, help_text="Enter the question text that you want displayed")
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
answer = models.CharField(max_length=100)
is_correct = models.BooleanField('Correct answer', default=False)
class QuizTaker(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
correct_answers = models.IntegerField(default=0)
completed = models.BooleanField(default=False)
attempt_number = models.AutoField(primary_key=True)
В моем html тест отображается следующим образом:
{% for q in question_list %}
{{q}} <br>
{% for choice in q.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.answer }}">
<label for="choice{{ forloop.counter }}">{{ choice.answer }}</label><br>
{% endfor %}
<a class='btn btn-warning save_ans' href="#">Save answer</a>
Ответ на каждый вопрос обрабатывается с помощью вызова ajax и отправляется в следующее представление:
ans_given = []
def save_ans(request):
ans = request.GET['ans']
ans_given.append(ans)
return HttpResponse(ans)
Я подошел к подсчету очков следующим образом:
ans_correct = []
answers = models.Choice.objects.filter(is_correct=True)
for i in answers:
scoring['ans_correct'].append(i.answer)
def quiz_results(request, pk):
score = 0
quiz = models.Quiz.objects.get(song__pk=pk)
count = quiz.questions_count
questions = models.Question.objects.filter(quiz=quiz)
for i in range(len(questions)):
if ans_given[i] == ans_correct[i]:
score =1
combined = list(zip(scoring['ans_correct'],scoring['ans_given']))
return render(request, 'quizzes/quiz_song_result.html', {'score': score, 'combined': combined})
И это работает нормально, но только в первый раз. Я хочу разрешить пользователю делать несколько попыток в викторине. После первого раза я получаю list index out of range
ошибку, которая, конечно, имеет смысл, потому что она сохранила первые n
ответы и добавила n
больше в список, в то время как длина ans_correct
, конечно, не меняется.
Я пробовал различные способы исправить это, но безрезультатно. Я пытался использовать insert
вместо append
, но не могу правильно выполнить индексацию. Я пытался помещать ans_given.clear()
в начало функции, чтобы каждый раз начинать с чистого списка, но он очищает список после каждого ответа (не после всего теста).
Я также пытался получить ответы, подобные этому:
for question in questions:
answer = models.Choice.objects.values_list('answer', flat=True).get(is_correct=True, question=question)
scoring['ans_correct'].append(answer)
А затем делаем подсчет очков аналогичным образом. В этом случае списки имеют, по крайней мере, одинаковую длину, но подсчет очков по-прежнему не работает, и это портит мой шаблон.
Я почти уверен, что для этого есть простое решение, и я просто не вижу этого. Или что есть гораздо лучший способ сделать то, что я хочу сделать … так что, если кто-нибудь может мне помочь, я был бы очень благодарен!
Редактировать: мне удалось решить мою проблему следующим образом (но я все еще жду предложений о том, как подойти к этому по-другому, даже если это означает большую часть переделки).
ans_user = ans_given[len(ans_given)-len(questions):]
ans_corr = ans_correct[len(ans_given)-len(questions):]
for i in range(len(questions)):
if ans_user[i] == ans_corr[i]:
score =1
Комментарии:
1. Разве вы не сохраняете ответ где-нибудь? Как передать значение ans_given
quiz_results
?2. Я просто добавляю это в
ans_given
список. Каждый ответ отправляется через ajax-запрос вsave_ans
представление. @ruddra