434 lines
16 KiB
Python
434 lines
16 KiB
Python
import uuid
|
|
from django.shortcuts import render, redirect, get_object_or_404
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.contrib.auth.models import User
|
|
from django.urls import reverse
|
|
from django.contrib import messages
|
|
from .models import QivipQuiz, QivipQuestion
|
|
from .forms import QuizForm, QuestionForm
|
|
import json
|
|
from django.core.paginator import Paginator
|
|
from .models import QivipQuiz
|
|
from .forms import QuizFilterForm
|
|
from django.db.models import Count
|
|
from django.contrib.auth.models import User
|
|
# Übersicht aller Quizze
|
|
|
|
def overview_quiz(request):
|
|
|
|
#Filter
|
|
form = QuizFilterForm(request.GET)
|
|
|
|
|
|
try:
|
|
|
|
filter_my_quizzes = QivipQuiz.objects.filter(user_id=request.user).annotate(max_amout_questions=Count('questions'))
|
|
except:
|
|
filter_my_quizzes = QivipQuiz.objects.none()
|
|
|
|
filter_other_quizzes = QivipQuiz.objects.annotate(max_amout_questions=Count('questions'))
|
|
|
|
|
|
|
|
if form.is_valid():
|
|
search = form.cleaned_data.get('search')
|
|
username= form.cleaned_data.get('user')
|
|
max_amout_questions= form.cleaned_data.get('max_amout_questions')
|
|
min_amout_questions= form.cleaned_data.get('min_amout_questions')
|
|
if search: # Suche nach Namen
|
|
filter_other_quizzes = filter_other_quizzes.filter(name__icontains=search)
|
|
filter_my_quizzes = filter_my_quizzes.filter(name__icontains=search)
|
|
|
|
if min_amout_questions:
|
|
filter_other_quizzes = filter_other_quizzes.filter(max_amout_questions__gte=min_amout_questions)
|
|
try:
|
|
filter_my_quizzes =filter_my_quizzes.filter(max_amout_questions__gte=min_amout_questions)
|
|
except:
|
|
filter_my_quizzes = QivipQuiz.objects.none()
|
|
|
|
if max_amout_questions:
|
|
filter_other_quizzes = filter_other_quizzes.filter(max_amout_questions__lte=max_amout_questions)
|
|
try:
|
|
filter_my_quizzes =filter_my_quizzes.filter(max_amout_questions__lte=max_amout_questions)
|
|
except:
|
|
filter_my_quizzes = QivipQuiz.objects.none()
|
|
|
|
if username:
|
|
try:
|
|
user = User.objects.get(username=username) # Benutzer anhand des Namens holen
|
|
filter_other_quizzes = filter_other_quizzes.filter(user_id=user.id)
|
|
filter_my_quizzes = filter_my_quizzes.filter(user_id=user.id) # Nach der user_id filtern
|
|
except User.DoesNotExist:
|
|
filter_other_quizzes = QivipQuiz.objects.none() # Falls User nicht existiert, leere Query zurückgeben
|
|
filter_my_quizzes = QivipQuiz.objects.none()
|
|
|
|
try:
|
|
filter_other_quizzes=filter_other_quizzes.exclude(user_id=request.user)
|
|
except:
|
|
filter_other_quizzes=filter_other_quizzes
|
|
|
|
|
|
|
|
filter_other_quizzes = filter_other_quizzes.filter(max_amout_questions__gte=1).filter(status='öffentlich')
|
|
|
|
context = {
|
|
'show_search': True,
|
|
'filter_my_quizzes': filter_my_quizzes.order_by('-creation_date'),
|
|
'filter_other_quizzes': filter_other_quizzes.order_by('-creation_date'),
|
|
'form': form,
|
|
}
|
|
|
|
|
|
return render(request, 'library/overview_quiz.html', context)
|
|
|
|
|
|
|
|
|
|
# Neues Quiz erstellen
|
|
@login_required
|
|
def new_quiz(request):
|
|
if request.method == 'POST':
|
|
form = QuizForm(request.POST, request.FILES)
|
|
if form.is_valid():
|
|
quiz = form.save(commit=False)
|
|
quiz.user_id = request.user
|
|
#quiz.creator = request.user
|
|
quiz.save()
|
|
form.save_m2m() # Speichert die Many-to-Many Beziehungen (Tags)
|
|
return redirect('library:detail_quiz', pk=quiz.pk)
|
|
|
|
else:
|
|
form = QuizForm()
|
|
return render(request, 'library/form.html', {'form': form})
|
|
|
|
# Quiz bearbeiten
|
|
@login_required
|
|
def edit_quiz(request, pk):
|
|
quiz = get_object_or_404(QivipQuiz, pk=pk, user_id=request.user)
|
|
if request.method == 'POST':
|
|
form = QuizForm(request.POST, instance=quiz, files=request.FILES)
|
|
if form.is_valid():
|
|
|
|
form.save()
|
|
return redirect('library:detail_quiz', pk=pk)
|
|
#return modified(request, pk)
|
|
|
|
else:
|
|
form = QuizForm(instance=quiz)
|
|
return render(request, 'library/form.html', {'form': form})
|
|
|
|
# Quiz löschen
|
|
@login_required
|
|
def delete_quiz(request, pk):
|
|
quiz = get_object_or_404(QivipQuiz, pk=pk, user_id=request.user)
|
|
if request.method == 'POST':
|
|
quiz.delete()
|
|
return redirect('library:overview_quiz')
|
|
return render(request, 'library/delete_confirmation.html', {'object': quiz})
|
|
|
|
# Quiz anzeigen
|
|
def detail_quiz(request, pk):
|
|
#quiz = get_object_or_404(QivipQuiz, pk=pk, user_id=request.user)
|
|
quiz = get_object_or_404(QivipQuiz, pk=pk)
|
|
show_answers = request.GET.get('show_answers', 'false').lower() == 'true'
|
|
questions = QivipQuestion.objects.filter(quiz_id=quiz)
|
|
# Parse JSON data for each question
|
|
for question in questions:
|
|
if question.data:
|
|
question.data = json.loads(question.data)
|
|
|
|
context = {
|
|
'quiz': quiz,
|
|
'questions': questions,
|
|
'detail':show_answers,
|
|
}
|
|
return render(request, 'library/detail_quiz.html', context)
|
|
"""
|
|
def modified(request, pk):
|
|
|
|
original_quiz = get_object_or_404(QivipQuiz, pk=pk)
|
|
words=original_quiz.modified_description.split()
|
|
word_exist=0
|
|
print(original_quiz.creator.username)
|
|
print(request.user.username)
|
|
|
|
for word in words:
|
|
|
|
if word==request.user.username or word+","==request.user.username:
|
|
word_exist=1
|
|
|
|
|
|
if word_exist==0 and len(words)!=0 and request.user.username!=original_quiz.creator.username:
|
|
original_quiz.modified_description +=", "+ request.user.username
|
|
|
|
|
|
elif word_exist==0 and request.user.username!=original_quiz.creator.username:
|
|
original_quiz.modified_description +=" "+ request.user.username
|
|
|
|
original_quiz.save()
|
|
|
|
return redirect('library:detail_quiz', pk=pk)
|
|
|
|
"""
|
|
|
|
@login_required
|
|
def copy_quiz(request, pk):
|
|
original_quiz = get_object_or_404(QivipQuiz, pk=pk)
|
|
|
|
|
|
# Quiz kopieren (ohne ID, damit ein neues Objekt erstellt wird)
|
|
|
|
# Quiz kopieren (ohne ID, damit ein neues Objekt erstellt wird)
|
|
|
|
new_quiz = original_quiz # Kopie erstellen (aber Achtung: Noch gleiche Referenz!)
|
|
new_quiz.pk = None # Setzt die ID auf None, damit Django es als neues Objekt erkennt
|
|
new_quiz.uuid = uuid.uuid4() # Neue UUID generieren
|
|
new_quiz.user_id = request.user # Neuer Besitzer ist der aktuelle User
|
|
new_quiz.name += " - Kopie" # Optional: Name anpassen
|
|
new_quiz.base_quiz_id = pk
|
|
#new_quiz.creator = original_quiz.creator or request.user
|
|
new_quiz.save() # Speichern als neues Objekt
|
|
# Optional: Beschreibung anpassen
|
|
# Alle zugehörigen Fragen kopieren
|
|
questions = QivipQuestion.objects.filter(quiz_id=pk)
|
|
for question in questions:
|
|
question.uuid = uuid.uuid4()
|
|
question.pk = None # Setze pk auf None, damit es als neues Objekt gespeichert wird
|
|
question.quiz_id = original_quiz # Verknüpfe mit dem neuen Quiz
|
|
question.data = question.data # `data`-Feld wird explizit übernommen # Verknüpfe mit dem neuen Quiz
|
|
question.save()
|
|
|
|
return redirect('library:detail_quiz', pk=new_quiz.pk)
|
|
|
|
|
|
# Übersicht aller Fragen
|
|
@login_required
|
|
def question_list(request):
|
|
questions = QivipQuestion.objects.filter(quiz_id__user_id=request.user)
|
|
|
|
# Parse JSON data for each question
|
|
for question in questions:
|
|
if question.data:
|
|
question.data = json.loads(question.data)
|
|
|
|
return render(request, 'library/question_list.html', {'questions': questions})
|
|
|
|
# Neue Frage erstellen
|
|
@login_required
|
|
def new_question(request):
|
|
question_type = request.GET.get('type')
|
|
quiz_id = request.GET.get('quiz_id')
|
|
|
|
if not quiz_id:
|
|
messages.error(request, 'Quiz ID muss angegeben werden.')
|
|
return redirect('library:overview_quiz')
|
|
|
|
try:
|
|
quiz = QivipQuiz.objects.get(pk=quiz_id, user_id=request.user)
|
|
except QivipQuiz.DoesNotExist:
|
|
messages.error(request, 'Quiz nicht gefunden oder keine Berechtigung.')
|
|
return redirect('library:overview_quiz')
|
|
|
|
if question_type not in ['multiple_choice', 'true_false']:
|
|
base_url = reverse('library:new_question')
|
|
return redirect(f'{base_url}?type=multiple_choice&quiz_id={quiz_id}')
|
|
|
|
if request.method == 'POST':
|
|
question_text = request.POST.get('question', '')
|
|
|
|
# Handle different question types
|
|
if question_type == 'true_false':
|
|
correct_answer = request.POST.get('correct_answer') == 'true'
|
|
json_data = {
|
|
'type': question_type,
|
|
'question': question_text,
|
|
'options': [
|
|
{'value': 'Wahr', 'is_correct': correct_answer},
|
|
{'value': 'Falsch', 'is_correct': not correct_answer}
|
|
]
|
|
}
|
|
elif question_type == 'multiple_choice':
|
|
options = []
|
|
i = 1
|
|
# Limit to maximum 6 options
|
|
while request.POST.get(f'option_{i}') and i <= 6:
|
|
is_correct = request.POST.get(f'correct_{i}') == '1'
|
|
options.append({
|
|
'order': i,
|
|
'value': request.POST.get(f'option_{i}'),
|
|
'is_correct': is_correct
|
|
})
|
|
i += 1
|
|
|
|
# Validate minimum 2 options
|
|
if len(options) < 2:
|
|
messages.error(request, 'Mindestens zwei Optionen müssen angegeben werden.')
|
|
return redirect(request.get_full_path())
|
|
|
|
json_data = {
|
|
'type': question_type,
|
|
'question': question_text,
|
|
'options': options
|
|
}
|
|
|
|
question = QivipQuestion()
|
|
question.data = json.dumps(json_data)
|
|
question.quiz_id = quiz
|
|
question.save()
|
|
#return modified(request, pk=quiz.pk)
|
|
return redirect('library:detail_quiz', pk=quiz.pk)
|
|
else:
|
|
# Initialize empty question data for new questions
|
|
if question_type == 'true_false':
|
|
question_data = {
|
|
'type': question_type,
|
|
'question': '',
|
|
'options': [
|
|
{'value': 'Wahr', 'is_correct': True},
|
|
{'value': 'Falsch', 'is_correct': False}
|
|
]
|
|
}
|
|
elif question_type == 'multiple_choice':
|
|
question_data = {
|
|
'type': question_type,
|
|
'question': '',
|
|
'options': [
|
|
{'value': '', 'is_correct': False},
|
|
{'value': '', 'is_correct': False}
|
|
]
|
|
}
|
|
|
|
template_name = f'library/question/question_{question_type}.html'
|
|
context = {
|
|
'question': question_data,
|
|
'quiz_id': quiz_id,
|
|
'quiz': quiz
|
|
}
|
|
|
|
return render(request, template_name, context)
|
|
|
|
# Frage bearbeiten
|
|
@login_required
|
|
def edit_question(request, pk):
|
|
question = get_object_or_404(QivipQuestion, pk=pk, quiz_id__user_id=request.user)
|
|
if question.quiz_id.user_id != request.user:
|
|
return redirect('library:question_list')
|
|
|
|
# Parse the existing JSON data
|
|
try:
|
|
question_data = json.loads(question.data) if question.data else {}
|
|
question_type = question_data.get('type', 'multiple_choice')
|
|
|
|
# For true/false questions, get the correct answer from the options
|
|
if question_type == 'true_false':
|
|
# Default to true if no options exist
|
|
correct_answer = True
|
|
if question_data.get('options'):
|
|
correct_answer = question_data['options'][0].get('is_correct', True)
|
|
question_data = {
|
|
'type': question_type,
|
|
'question': question_data.get('question', ''),
|
|
'correct_answer': correct_answer, # Add this for template compatibility
|
|
'options': [
|
|
{'value': 'Wahr', 'is_correct': correct_answer},
|
|
{'value': 'Falsch', 'is_correct': not correct_answer}
|
|
]
|
|
}
|
|
else:
|
|
# For multiple choice questions
|
|
question_data.setdefault('type', question_type)
|
|
question_data.setdefault('question', '')
|
|
question_data.setdefault('options', [])
|
|
|
|
except (json.JSONDecodeError, AttributeError):
|
|
# Handle invalid JSON or None data
|
|
question_type = question_data.get('type', 'multiple_choice')
|
|
if question_type == 'true_false':
|
|
question_data = {
|
|
'type': question_type,
|
|
'question': '',
|
|
'correct_answer': True, # Default to true for new questions
|
|
'options': [
|
|
{'value': 'Wahr', 'is_correct': True},
|
|
{'value': 'Falsch', 'is_correct': False}
|
|
]
|
|
}
|
|
else:
|
|
question_data = {
|
|
'type': question_type,
|
|
'question': '',
|
|
'options': []
|
|
}
|
|
|
|
if request.method == 'POST':
|
|
question_text = request.POST.get('question', '')
|
|
|
|
# Handle different question types
|
|
if question_type == 'true_false':
|
|
correct_answer = request.POST.get('correct_answer') == 'true'
|
|
json_data = {
|
|
'type': question_type,
|
|
'question': question_text,
|
|
'options': [
|
|
{'value': 'Wahr', 'is_correct': correct_answer},
|
|
{'value': 'Falsch', 'is_correct': not correct_answer}
|
|
]
|
|
}
|
|
elif question_type == 'multiple_choice':
|
|
options = []
|
|
i = 1
|
|
# Limit to maximum 6 options
|
|
while request.POST.get(f'option_{i}') and i <= 6:
|
|
options.append({
|
|
'order': i,
|
|
'value': request.POST.get(f'option_{i}'),
|
|
'is_correct': request.POST.get(f'correct_{i}') == '1'
|
|
})
|
|
i += 1
|
|
|
|
# Validate minimum 2 options
|
|
if len(options) < 2:
|
|
messages.error(request, 'Mindestens zwei Optionen müssen angegeben werden.')
|
|
return redirect(request.get_full_path())
|
|
|
|
# Validate maximum 6 options
|
|
if len(options) > 6:
|
|
messages.error(request, 'Maximal 6 Optionen sind erlaubt.')
|
|
return redirect(request.get_full_path())
|
|
|
|
json_data = {
|
|
'type': question_type,
|
|
'question': question_text,
|
|
'options': options
|
|
}
|
|
|
|
question.data = json.dumps(json_data)
|
|
question.save()
|
|
#return modified(request, question.quiz_id.pk)
|
|
return redirect('library:detail_quiz', pk=question.quiz_id.pk)
|
|
|
|
else:
|
|
template_name = f'library/question/question_{question_type}.html'
|
|
context = {
|
|
'question': {'data': question_data}, # Wrap in data structure expected by template
|
|
'quiz_id': question.quiz_id.pk,
|
|
'quiz': question.quiz_id
|
|
}
|
|
|
|
return render(request, template_name, context)
|
|
|
|
|
|
# Frage löschen
|
|
@login_required
|
|
def delete_question(request, pk):
|
|
question = get_object_or_404(QivipQuestion, pk=pk, quiz_id__user_id=request.user)
|
|
|
|
# Parse JSON data for question
|
|
if question.data:
|
|
question.data = json.loads(question.data)
|
|
|
|
if request.method == 'POST':
|
|
question.delete()
|
|
return redirect('library:detail_quiz', pk=question.quiz_id.pk)
|
|
return render(request, 'library/delete_confirmation.html', {'object': question})
|