150 lines
4.7 KiB
Python
150 lines
4.7 KiB
Python
from django.http import HttpResponse, HttpResponseRedirect
|
|
from django.shortcuts import render, redirect, get_object_or_404
|
|
from django.urls import reverse
|
|
from django.views.decorators.http import require_http_methods
|
|
from django.db.models import Q
|
|
|
|
from .models import Question, QuizResult, Tag
|
|
from .forms import CreateQuizForm
|
|
|
|
|
|
def handle_tag_filter(request):
|
|
tag_slug = request.GET.get('tag')
|
|
if tag_slug is not None:
|
|
if tag_slug == "":
|
|
if 'quiz_tag' in request.session:
|
|
del request.session['quiz_tag']
|
|
else:
|
|
request.session['quiz_tag'] = tag_slug
|
|
|
|
def create_quiz(request):
|
|
if request.method == 'POST':
|
|
form = CreateQuizForm(request.POST)
|
|
if form.is_valid():
|
|
# clear existing session data
|
|
keys_to_clear = ['quiz_filter_course_id', 'quiz_filter_tag_ids', 'quiz_filter_types', 'quiz_tag']
|
|
for key in keys_to_clear:
|
|
if key in request.session:
|
|
del request.session[key]
|
|
|
|
course = form.cleaned_data.get('course')
|
|
tags = form.cleaned_data.get('tags')
|
|
question_types = form.cleaned_data.get('question_type')
|
|
|
|
if course:
|
|
request.session['quiz_filter_course_id'] = course.id
|
|
|
|
if tags:
|
|
request.session['quiz_filter_tag_ids'] = list(tags.values_list('id', flat=True))
|
|
|
|
if question_types:
|
|
request.session['quiz_filter_types'] = question_types
|
|
|
|
return redirect('next_question')
|
|
else:
|
|
form = CreateQuizForm()
|
|
|
|
return render(request, 'quiz_create.html', {'form': form})
|
|
|
|
def index(request):
|
|
handle_tag_filter(request)
|
|
total_questions = Question.objects.count()
|
|
answered_count = QuizResult.objects.filter(user=request.quiz_user).count()
|
|
|
|
context = {
|
|
'total_questions': total_questions,
|
|
'answered_count': answered_count,
|
|
'tags': Tag.objects.all(),
|
|
'current_tag': request.session.get('quiz_tag'),
|
|
}
|
|
return render(request, 'index.html', context)
|
|
|
|
|
|
def get_next_question(request):
|
|
# Handle tag filtering
|
|
handle_tag_filter(request)
|
|
|
|
current_tag = request.session.get('quiz_tag')
|
|
|
|
# New filters
|
|
filter_course_id = request.session.get('quiz_filter_course_id')
|
|
filter_tag_ids = request.session.get('quiz_filter_tag_ids')
|
|
filter_types = request.session.get('quiz_filter_types')
|
|
|
|
answered_ids = QuizResult.objects.filter(user=request.quiz_user).values_list('question_id', flat=True)
|
|
|
|
questions = Question.objects.exclude(id__in=answered_ids)
|
|
|
|
# Apply filters
|
|
if current_tag:
|
|
questions = questions.filter(tags__slug=current_tag)
|
|
|
|
if filter_course_id:
|
|
questions = questions.filter(exam__course_id=filter_course_id)
|
|
|
|
if filter_tag_ids:
|
|
questions = questions.filter(tags__id__in=filter_tag_ids)
|
|
|
|
if filter_types:
|
|
# "single" -> no comma
|
|
# "multi" -> comma
|
|
q_objs = Q()
|
|
if 'single' in filter_types:
|
|
q_objs |= ~Q(correct_answer__contains=',')
|
|
if 'multi' in filter_types:
|
|
q_objs |= Q(correct_answer__contains=',')
|
|
|
|
if q_objs:
|
|
questions = questions.filter(q_objs)
|
|
|
|
# Distinguish questions based on filters to ensure we don't get duplicates if filtering by many-to-many
|
|
questions = questions.distinct()
|
|
|
|
next_question = questions.first()
|
|
|
|
if not next_question:
|
|
return render(request, 'partials/complete.html')
|
|
|
|
return render(request, 'partials/question.html', {'question': next_question})
|
|
|
|
|
|
@require_http_methods(["POST"])
|
|
def submit_answer(request):
|
|
question_id = request.POST.get('question_id')
|
|
selected_answer = request.POST.get('answer')
|
|
|
|
if not question_id or not selected_answer:
|
|
return HttpResponse("Invalid submission", status=400)
|
|
|
|
try:
|
|
question = Question.objects.get(id=question_id)
|
|
except Question.DoesNotExist:
|
|
return HttpResponse("Question not found", status=404)
|
|
|
|
is_correct = selected_answer == question.correct_answer
|
|
|
|
QuizResult.objects.update_or_create(
|
|
user=request.quiz_user,
|
|
question=question,
|
|
defaults={
|
|
'selected_answer': selected_answer,
|
|
'is_correct': is_correct,
|
|
}
|
|
)
|
|
|
|
return get_next_question(request)
|
|
|
|
|
|
def stats(request):
|
|
results = QuizResult.objects.filter(user=request.quiz_user)
|
|
total = results.count()
|
|
correct = results.filter(is_correct=True).count()
|
|
|
|
context = {
|
|
'total': total,
|
|
'correct': correct,
|
|
'percentage': round((correct / total * 100) if total > 0 else 0, 1),
|
|
}
|
|
return render(request, 'stats.html', context)
|
|
|