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('question')) except: filter_my_quizzes = QivipQuiz.objects.none() filter_other_quizzes = QivipQuiz.objects.annotate(max_amout_questions=Count('question')) 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) 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 } 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})