From 93e166ece09522f6643ac054947eed2330d350db Mon Sep 17 00:00:00 2001 From: ben8 Date: Fri, 27 Jun 2025 15:17:27 +0200 Subject: [PATCH] =?UTF-8?q?Bewertung=5Ffix=20und=20Ver=C3=B6ffentlichungsz?= =?UTF-8?q?eit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- django/core/settings.py | 1 + django/library/admin.py | 4 +- .../migrations/0055_qivipquiz_published_at.py | 18 ++++++ .../0056_alter_quizrating_unique_together.py | 17 +++++ django/library/models.py | 25 ++++++-- django/library/views.py | 29 ++++++++- django/play/consumers/game.py | 14 ++++- django/play/views.py | 62 +++++++++++++------ django/templates/library/overview_quiz.html | 41 +++++++----- .../library/overview_quiz_favorite.html | 16 ++++- .../templates/library/overview_quiz_my.html | 18 +++++- 11 files changed, 195 insertions(+), 50 deletions(-) create mode 100644 django/library/migrations/0055_qivipquiz_published_at.py create mode 100644 django/library/migrations/0056_alter_quizrating_unique_together.py diff --git a/django/core/settings.py b/django/core/settings.py index ecd2302..7506dee 100644 --- a/django/core/settings.py +++ b/django/core/settings.py @@ -56,6 +56,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'channels', 'django_cleanup', + 'django.contrib.humanize', ] MIDDLEWARE = [ diff --git a/django/library/admin.py b/django/library/admin.py index 663fdf7..320771f 100644 --- a/django/library/admin.py +++ b/django/library/admin.py @@ -1,9 +1,9 @@ from django.contrib import admin -from .models import QivipQuiz, QivipQuestion, QivipQuizFavorite, QuestionImage, QuizCategory, QuizImage +from .models import QivipQuiz, QivipQuestion, QivipQuizFavorite, QuestionImage, QuizCategory, QuizImage, QuizRating # Für das QivipQuiz Modell class QivipQuizAdmin(admin.ModelAdmin): - list_display = ('name', 'user_id', 'status', 'category', 'creation_date', 'update_date') # Welche Felder sollen in der Übersicht angezeigt werden + list_display = ('name','published_at', 'user_id', 'status', 'category', 'creation_date', 'update_date') # Welche Felder sollen in der Übersicht angezeigt werden search_fields = ('name', 'user_id__username', 'category__name') # Suchfelder list_filter = ('status', 'category') # Filteroptionen # Für das QivipQuestion Modell diff --git a/django/library/migrations/0055_qivipquiz_published_at.py b/django/library/migrations/0055_qivipquiz_published_at.py new file mode 100644 index 0000000..4de7157 --- /dev/null +++ b/django/library/migrations/0055_qivipquiz_published_at.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.7 on 2025-06-26 16:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0054_qivipquestion_credits'), + ] + + operations = [ + migrations.AddField( + model_name='qivipquiz', + name='published_at', + field=models.DateTimeField(blank=True, null=True), + ), + ] diff --git a/django/library/migrations/0056_alter_quizrating_unique_together.py b/django/library/migrations/0056_alter_quizrating_unique_together.py new file mode 100644 index 0000000..53ac17a --- /dev/null +++ b/django/library/migrations/0056_alter_quizrating_unique_together.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1.7 on 2025-06-27 12:35 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0055_qivipquiz_published_at'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='quizrating', + unique_together=set(), + ), + ] diff --git a/django/library/models.py b/django/library/models.py index eb1b3de..87d10f6 100644 --- a/django/library/models.py +++ b/django/library/models.py @@ -3,7 +3,7 @@ from django.contrib.auth.models import User from django.utils.text import slugify import uuid from django.core.exceptions import ValidationError - +from django.utils import timezone class QuizImage(models.Model): image = models.ImageField(max_length=256,verbose_name="Bild", upload_to='quiz_images/', blank=True, null=True) # Bild speichern in media/quiz_images/ @@ -59,6 +59,10 @@ class QivipQuiz(models.Model): credits=models.TextField(blank=True, editable=True) average_rating = models.FloatField(default=3.0) rating_count = models.IntegerField(default=0) + published_at = models.DateTimeField(null=True, blank=True) # manuell gesetzt, wenn veröffentlicht + + def is_published(self): + return self.published_at is not None and self.published_at <= timezone.now() def __str__(self): return self.name @@ -111,9 +115,22 @@ class QuizRating(models.Model): rating = models.IntegerField(choices=[(i, str(i)) for i in range(1, 6)]) created_at = models.DateTimeField(auto_now_add=True) - class Meta: - unique_together = ('quiz', 'participant_id') + #class Meta: + #unique_together = ('quiz', 'participant_id') + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + + # Update quiz average rating (immer, auch bei Updates) + quiz = self.quiz + total_ratings = quiz.ratings.count() + avg_rating = quiz.ratings.aggregate(models.Avg('rating'))['rating__avg'] + quiz.average_rating = round(avg_rating, 1) if avg_rating else 3.0 + quiz.rating_count = total_ratings + quiz.save() + + +""" def save(self, *args, **kwargs): is_new = self.pk is None super().save(*args, **kwargs) @@ -125,7 +142,7 @@ class QuizRating(models.Model): avg_rating = quiz.ratings.aggregate(models.Avg('rating'))['rating__avg'] quiz.average_rating = round(avg_rating, 1) if avg_rating else 3.0 quiz.rating_count = total_ratings - quiz.save() + quiz.save()""" class QuizCategory(models.Model): name = models.CharField(max_length=100, unique=True) diff --git a/django/library/views.py b/django/library/views.py index 4bf4860..2a71b50 100644 --- a/django/library/views.py +++ b/django/library/views.py @@ -318,10 +318,11 @@ def favorite_quiz(request, pk): if favorite: favorite.favorite=not favorite.favorite + if favorite.favorite==True: - favorite.favorite_date = timezone.now() + favorite.favorite_date = timezone.now() favorite.save() else: favorite.favorite_date = None @@ -347,10 +348,19 @@ def new_quiz(request): form = QuizForm(request.POST, request.FILES) + + + if form.is_valid(): quiz = form.save(commit=False) + status = form.cleaned_data.get('status') + + if status == 'öffentlich' and not quiz.published_at: + quiz.published_at = timezone.now() + try: quiz_image=request.FILES['quiz_image'] + imagequiz=QuizImage.objects.create(image=quiz_image) quiz.image=imagequiz @@ -359,6 +369,8 @@ def new_quiz(request): quiz.user_id = request.user + + #quiz.creator = request.user quiz.save() #form.save_m2m() # Speichert die Many-to-Many Beziehungen (Tags) @@ -373,9 +385,14 @@ def new_quiz(request): 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) + form = QuizForm(request.POST, instance=quiz, files=request.FILES) + + + if form.is_valid(): + + if 'reset_image' in request.POST: quiz.image = None @@ -388,7 +405,12 @@ def edit_quiz(request, pk): except: pass - + quiz = form.save(commit=False) + + # Beispiel: Status aus dem Formular holen + status = form.cleaned_data.get('status') + if status == 'öffentlich' and not quiz.published_at: + quiz.published_at = timezone.now() form.save() for img in QuizImage.objects.all(): @@ -466,6 +488,7 @@ def copy_quiz(request, pk): new_quiz.base_quiz_id = pk new_quiz.rating_count = 0 new_quiz.average_rating = 3.0 + new_quiz.published_at = timezone.now() new_quiz.save() # Speichern als neues Objekt # Optional: Beschreibung anpassen # Alle zugehörigen Fragen kopieren diff --git a/django/play/consumers/game.py b/django/play/consumers/game.py index d4fa0ff..46da8ef 100644 --- a/django/play/consumers/game.py +++ b/django/play/consumers/game.py @@ -264,6 +264,7 @@ class GameConsumer(AsyncWebsocketConsumer): @database_sync_to_async def save_rating(self, participant_id, rating): + from django.db import models if not settings.QIVIP_CONFIG['ENABLE_RATING_SYSTEM']: return False from library.models import QuizRating @@ -275,15 +276,22 @@ class GameConsumer(AsyncWebsocketConsumer): ) # Update or create rating + """ rating_obj, created = QuizRating.objects.get_or_create( quiz=game.quiz_id, participant_id=participant_id, defaults={'rating': rating} ) + """ + rating_obj=QuizRating.objects.create( + quiz=game.quiz_id, + participant_id=participant_id, + rating=rating) - if not created: - rating_obj.rating = rating - rating_obj.save() + rating_obj.rating = rating + rating_obj.save() + + return True except (QuizGame.DoesNotExist, QuizGameParticipant.DoesNotExist): diff --git a/django/play/views.py b/django/play/views.py index edce002..025b6d6 100644 --- a/django/play/views.py +++ b/django/play/views.py @@ -147,26 +147,7 @@ def join_game(request): messages.error(request, "Dieses Spiel existiert nicht.") return render(request, 'play/join_game.html') -def finished(request, join_code): - try: - game = QuizGame.objects.get(join_code=join_code) - participant = None - participant_id = request.session.get('participant_id') - if participant_id: - participant = QuizGameParticipant.objects.filter( - quiz_game=game, - participant_id=participant_id - ).first() - context = { - 'join_code': join_code, - 'is_host': str(game.host_id) == str(request.session.get('host_id')), - 'participant_id': participant_id if participant else None, - 'rating_enabled': settings.QIVIP_CONFIG['ENABLE_RATING_SYSTEM'] - } - return render(request, 'play/game/finished.html', context) - except QuizGame.DoesNotExist: - return redirect('home') def scores(request, join_code): quiz_game = get_object_or_404(QuizGame, join_code=join_code) @@ -207,8 +188,9 @@ def scores(request, join_code): 'question_index': quiz_game.current_question_index, 'total_questions': len(questions) }) - +""" def finished(request, join_code): + quiz_game = get_object_or_404(QuizGame, join_code=join_code) # Verify game state @@ -240,6 +222,46 @@ def finished(request, join_code): 'is_host': is_host, 'participant_id': participant_id if participant else None }) +""" + + + +def finished(request, join_code): + quiz_game = get_object_or_404(QuizGame, join_code=join_code) + + if quiz_game.current_state != 'finished': + return redirect('play:lobby', join_code=join_code) + try: + game = QuizGame.objects.get(join_code=join_code) + # Get participants sorted by score + participants = QuizGameParticipant.objects.filter(quiz_game=quiz_game).order_by('-score') + + + # Get participant if exists + participant_id = request.COOKIES.get('participant_id') + participant = None + if participant_id: + participant = QuizGameParticipant.objects.filter( + quiz_game=quiz_game, + participant_id=participant_id + ).first() + + is_host = False + if 'host_id' in request.COOKIES and request.COOKIES['host_id'] == quiz_game.host_id: + is_host = True + + context = { + 'join_code': join_code, + 'is_host': is_host, + 'participants': participants, + 'participant_id': participant_id if participant else None, + 'rating_enabled': settings.QIVIP_CONFIG['ENABLE_RATING_SYSTEM'] + } + return render(request, 'play/game/finished.html', context) + except QuizGame.DoesNotExist: + return redirect('home') + + def question(request, join_code): quiz_game = get_object_or_404(QuizGame, join_code=join_code) diff --git a/django/templates/library/overview_quiz.html b/django/templates/library/overview_quiz.html index 77eeccc..8385da2 100644 --- a/django/templates/library/overview_quiz.html +++ b/django/templates/library/overview_quiz.html @@ -1,6 +1,6 @@ {% extends 'base.html' %} {% load static %} - +{% load humanize %} {% block extra_css %}