Views для прохождения теста на Django
Кратко про проект: Нужно сделать веб-ресурс для оценки знаний(прохождения тестов) Вот основные файлы
models.py
class Test(models.Model):
title = models.CharField("Название", max_length=100, unique=True)
description = models.TextField("Описание")
question_count = models.IntegerField("Количество вопросов", default=0)
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="author")
class Question(models.Model):
test = models.ForeignKey(Test, verbose_name="Тест", on_delete=models.CASCADE, related_name='questions')
question_text = models.TextField("Вопрос")
num_question = models.IntegerField("Номер вопроса:", default=1)
class Answer(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='answers')
answer_text1 = models.TextField("Текст першої відповіді")
is_correct1 = models.BooleanField("Перша відповідь є правильною", default=False)
answer_text2 = models.TextField("Текст другої відповіді")
is_correct2 = models.BooleanField("Друга відповідь є правильною", default=False)
answer_text3 = models.TextField("Текст третьої відповіді")
is_correct3 = models.BooleanField("Третя відповідь є правильною", default=False)
answer_text4 = models.TextField("Текст четвертої відповіді")
is_correct4 = models.BooleanField("Четверта відповідь є правильною", default=False)
class Result(models.Model):
user = models.ForeignKey(User, verbose_name="Пользователь", on_delete=models.CASCADE, related_name='userResult')
test = models.ForeignKey(Test,verbose_name="Тест", on_delete=models.CASCADE, related_name='testResult')
score = models.IntegerField("Оценка")
urls.py
urlpatterns = [
path('', views.ShowTestView.as_view(), name = 'home'),
path('test/add/', views.CreateTestView.as_view(), name='test_add'),
path('test/<int:pk>/pass/', views.PassTestView.as_view(), name='test_pass'),
path('test/<int:pk>/update/', views.UpdateTestView.as_view(), name='test_update'),
path('test/<int:test_id>/add/', views.CreateQuestionView.as_view(), name='question_add'),
path('test/<int:test_id>/add/<int:question_id>/', views.CreateAnswerView.as_view(), name='answer_add'),
path('test/<int:test_id>/result/', views.TestResultsView.as_view(), name='test_result'),
path('contact/', views.contact, name = 'contact'),
]
forms.py
class TestForm(forms.ModelForm):
class Meta:
model = TestModel
fields = ['title', 'description', 'question_count']
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'description': forms.Textarea(attrs={'class': 'form-control'}),
'question_count': forms.NumberInput(attrs={'class': 'form-control'}),
}
class QuestionForm(forms.ModelForm):
class Meta:
model = Question
fields = ['question_text', 'num_question']
widgets = {
'question_text': forms.Textarea(attrs={'class': 'form-control'}),
'num_question': forms.NumberInput(attrs={'class': 'form-control'}),
}
class AnswerForm(forms.ModelForm):
class Meta:
model = Answer
fields = ['answer_text1', 'is_correct1', 'answer_text2', 'is_correct2', 'answer_text3', 'is_correct3', 'answer_text4', 'is_correct4']
widgets = {
'answer_text1': forms.TextInput(attrs={'class': 'form-control'}),
'is_correct1': forms.CheckboxInput(attrs={'class': 'form-check-input mb-5'}),
'answer_text2': forms.TextInput(attrs={'class': 'form-control'}),
'is_correct2': forms.CheckboxInput(attrs={'class': 'form-check-input mb-5'}),
'answer_text3': forms.TextInput(attrs={'class': 'form-control'}),
'is_correct3': forms.CheckboxInput(attrs={'class': 'form-check-input mb-5'}),
'answer_text4': forms.TextInput(attrs={'class': 'form-control'}),
'is_correct4': forms.CheckboxInput(attrs={'class': 'form-check-input mb-5'}),
}
class PassTestForm(forms.ModelForm):
class Meta:
model = Result
fields = ['score']
widgets = {
'score': forms.TextInput(attrs={'class': 'form-control'}),
}
def __init__(self, *args, **kwargs):
super(PassTestForm, self).__init__(*args, **kwargs)
views.py
class PassTestView(View):
def get(self, request, pk):
test = get_object_or_404(TestModels, pk=pk)
questions = test.questions.all()
form = PassTestForm()
return render(request, 'courses/pass_test.html', {'test': test, 'questions': questions, 'form': form})
def post(self, request, pk):
test = get_object_or_404(TestModels, pk=pk)
form = PassTestForm(request.POST)
if form.is_valid():
score = 0
for question in test.questions.all():
selected_answers = request.POST.getlist(f'question_{question.id}')
correct_answers = Answer.objects.filter(question=question, is_correct=True)
if set(selected_answers) == set(str(answer.id) for answer in correct_answers):
score += 1
result = Result.objects.create(user=request.user, test=test, score=score)
messages.success(request, 'Результати тестування збережено успішно.')
return redirect('test_results', test_id=pk) # Ось тут змінено ім'я шляху
else:
questions = test.questions.all()
return render(request, 'courses/pass_test.html', {'test': test, 'questions': questions, 'form': form})
class TestResultsView(View):
def get(self, request, test_id):
results = Result.objects.filter(test_id=test_id)
context = {
'results': results,
}
return render(request, 'courses/test_result.html', context)
pass_test.html
{% block content %}
<h1 class="mb-5">{{ test.title }}</h1>
<form method="post">
{% csrf_token %}
{% for question in questions %}
<div class="mb-5">
<h2 class="mb-3">Питання №{{ question.num_question }}: {{ question.question_text }}</h2>
{% for answer in question.answers.all %}
<div class="form-check ml-4 mb-2">
<input class="form-check-input" type="radio" id="answer{{ answer.id }}" name="question{{ question.id }}" value="{{ answer.id }}">
<label class="form-check-label" for="answer{{ answer.id }}">{{ answer.answer_text1 }}</label>
</div>
<div class="form-check ml-4 mb-2">
<input class="form-check-input" type="radio" id="answer{{ answer.id }}" name="question{{ question.id }}" value="{{ answer.id }}">
<label class="form-check-label" for="answer{{ answer.id }}">{{ answer.answer_text2 }}</label>
</div>
<div class="form-check ml-4 mb-2">
<input class="form-check-input" type="radio" id="answer{{ answer.id }}" name="question{{ question.id }}" value="{{ answer.id }}">
<label class="form-check-label" for="answer{{ answer.id }}">{{ answer.answer_text3 }}</label>
</div>
<div class="form-check ml-4 mb-2">
<input class="form-check-input" type="radio" id="answer{{ answer.id }}" name="question{{ question.id }}" value="{{ answer.id }}">
<label class="form-check-label" for="answer{{ answer.id }}">{{ answer.answer_text4 }}</label>
</div>
{% endfor %}
</div>
{% endfor %}
<button type="submit" class="btn btn-secondary rounded-pill px-3">Завершити тест</button>
</form>
{% endblock %}
Ошибка в том что при нажатии кнопки закончить тест мы остаемся на странице прохождения теста(кнопка = submit) Может ошибка очень простая, я гуглил, решения не нашел, доп файли прикреплю если надо