From 087d4cdddd11914ccf2bda555aaae29a4520ac49 Mon Sep 17 00:00:00 2001 From: ben8 Date: Thu, 10 Apr 2025 15:47:47 +0200 Subject: [PATCH 01/14] #67 Spiel_button_beiEditInterface_und_kldesignchanges --- django/templates/library/detail_quiz.html | 54 ++++++++++++++++------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/django/templates/library/detail_quiz.html b/django/templates/library/detail_quiz.html index cecf631..06ec9e7 100644 --- a/django/templates/library/detail_quiz.html +++ b/django/templates/library/detail_quiz.html @@ -3,29 +3,51 @@ {% block content %}
-
-

{{ quiz.name }}

-
+ +
+

{{ quiz.name }}

+ +
+ +
{% if quiz.user_id == request.user %} - + - + - {% endif %} - - - - -   Quiz kopieren -
+ {% endif %} + +
+ +
{% if quiz.description %} @@ -62,18 +84,18 @@
-
+

Fragen

-
+
{% if quiz.user_id == request.user %} + class=" mt-1 bg-blue-100 text-blue-800 px-4 py-2 rounded-md text-xs lg:text-lg hover:border-blue-600 border-2"> Multiple Choice {% endif %} {% if quiz.user_id == request.user %} + class=" mt-1 bg-purple-100 text-purple-800 px-4 py-2 rounded-md text-xs lg:text-lg hover:border-blue-600 border-2"> Wahr/Falsch {% endif %} From a39c944f103a33db7d4c0a6c6bf193bc756b944e Mon Sep 17 00:00:00 2001 From: ben8 Date: Thu, 10 Apr 2025 16:09:51 +0200 Subject: [PATCH 02/14] =?UTF-8?q?tags=5Fgel=C3=B6cscht+status=5Fversteckt?= =?UTF-8?q?=5Fentfernt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- django/library/admin.py | 4 ++-- django/library/forms.py | 2 +- .../0033_remove_qivipquiz_tags_delete_tag.py | 20 +++++++++++++++++++ .../migrations/0034_alter_qivipquiz_status.py | 18 +++++++++++++++++ django/library/models.py | 7 +------ 5 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 django/library/migrations/0033_remove_qivipquiz_tags_delete_tag.py create mode 100644 django/library/migrations/0034_alter_qivipquiz_status.py diff --git a/django/library/admin.py b/django/library/admin.py index 6526f60..685ee1c 100644 --- a/django/library/admin.py +++ b/django/library/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models import QivipQuiz, QivipQuestion, QuizCategory, Tag +from .models import QivipQuiz, QivipQuestion, QuizCategory # Für das QivipQuiz Modell class QivipQuizAdmin(admin.ModelAdmin): @@ -27,4 +27,4 @@ class TagAdmin(admin.ModelAdmin): admin.site.register(QivipQuiz, QivipQuizAdmin) admin.site.register(QivipQuestion, QivipQuestionAdmin) admin.site.register(QuizCategory, QuizCategoryAdmin) -admin.site.register(Tag, TagAdmin) + diff --git a/django/library/forms.py b/django/library/forms.py index c454b71..958ae7b 100644 --- a/django/library/forms.py +++ b/django/library/forms.py @@ -4,7 +4,7 @@ from .models import QivipQuiz, QivipQuestion class QuizForm(forms.ModelForm): class Meta: model = QivipQuiz - fields = ['name', 'description','image', 'status', 'category', 'tags',"difficulty","credits"] + fields = ['name', 'description','image', 'status', 'category', "difficulty","credits"] class QuestionForm(forms.ModelForm): class Meta: diff --git a/django/library/migrations/0033_remove_qivipquiz_tags_delete_tag.py b/django/library/migrations/0033_remove_qivipquiz_tags_delete_tag.py new file mode 100644 index 0000000..680c87a --- /dev/null +++ b/django/library/migrations/0033_remove_qivipquiz_tags_delete_tag.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.7 on 2025-04-10 13:59 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0032_qivipquiz_average_rating_qivipquiz_rating_count_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='qivipquiz', + name='tags', + ), + migrations.DeleteModel( + name='Tag', + ), + ] diff --git a/django/library/migrations/0034_alter_qivipquiz_status.py b/django/library/migrations/0034_alter_qivipquiz_status.py new file mode 100644 index 0000000..27a3a46 --- /dev/null +++ b/django/library/migrations/0034_alter_qivipquiz_status.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.7 on 2025-04-10 14:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0033_remove_qivipquiz_tags_delete_tag'), + ] + + operations = [ + migrations.AlterField( + model_name='qivipquiz', + name='status', + field=models.CharField(choices=[('öffentlich', 'Öffentlich'), ('privat', 'Privat')], default='öffentlich', max_length=10), + ), + ] diff --git a/django/library/models.py b/django/library/models.py index ceb2eb5..82fcc5a 100644 --- a/django/library/models.py +++ b/django/library/models.py @@ -7,7 +7,7 @@ from django.core.exceptions import ValidationError class QivipQuiz(models.Model): STATUS_VALUES = { "öffentlich": "Öffentlich", - "versteckt": "Versteckt", + #"versteckt": "Versteckt", "privat": "Privat", } DIFFICULTY_VALUES = { @@ -33,7 +33,6 @@ class QivipQuiz(models.Model): update_date = models.DateTimeField(auto_now=True) status = models.CharField(max_length=10, choices=list(STATUS_VALUES.items()), default="öffentlich") category = models.ForeignKey('QuizCategory', related_name='quiz', on_delete=models.CASCADE) - tags = models.ManyToManyField('Tag', blank=True) name = models.CharField(max_length=75) description = models.TextField(validators=[validate_description],max_length=200,blank=False, default="In dem Quiz geht es um ...") difficulty= models.CharField(max_length=13, choices=list(DIFFICULTY_VALUES.items()), default="nicht gesetzt", help_text="1: niedrigste Schwierigkeit und 5: höchste Schwierigkeit") @@ -57,11 +56,7 @@ class QivipQuestion(models.Model): def __str__(self): return self.data[:50] -class Tag(models.Model): - name = models.CharField(max_length=100, unique=True) - def __str__(self): - return self.name class QuizRating(models.Model): quiz = models.ForeignKey(QivipQuiz, on_delete=models.CASCADE, related_name='ratings') From 7ce0e6e9dd27df38cc46464f5cd29ffdb5cdcc39 Mon Sep 17 00:00:00 2001 From: ben8 Date: Thu, 10 Apr 2025 19:55:11 +0200 Subject: [PATCH 03/14] Zwischenstand_Favoriten --- django/library/admin.py | 12 +- .../migrations/0035_qivipquiz_favorite.py | 18 ++ ..._remove_qivipquiz_favorite_quizfavorite.py | 32 +++ ...7_rename_quizfavorite_qivipquizfavorite.py | 19 ++ .../0038_alter_qivipquizfavorite_quiz.py | 19 ++ django/library/models.py | 7 + django/library/urls.py | 1 + django/library/views.py | 27 +- django/templates/library/overview_quiz.html | 249 +++++++++++++++++- 9 files changed, 373 insertions(+), 11 deletions(-) create mode 100644 django/library/migrations/0035_qivipquiz_favorite.py create mode 100644 django/library/migrations/0036_remove_qivipquiz_favorite_quizfavorite.py create mode 100644 django/library/migrations/0037_rename_quizfavorite_qivipquizfavorite.py create mode 100644 django/library/migrations/0038_alter_qivipquizfavorite_quiz.py diff --git a/django/library/admin.py b/django/library/admin.py index 685ee1c..7d617a5 100644 --- a/django/library/admin.py +++ b/django/library/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models import QivipQuiz, QivipQuestion, QuizCategory +from .models import QivipQuiz, QivipQuestion, QivipQuizFavorite, QuizCategory # Für das QivipQuiz Modell class QivipQuizAdmin(admin.ModelAdmin): @@ -18,13 +18,13 @@ class QuizCategoryAdmin(admin.ModelAdmin): search_fields = ('name',) prepopulated_fields = {'slug': ('name',)} # Erstelle automatisch den Slug basierend auf dem Namen -# Für das Tag Modell -class TagAdmin(admin.ModelAdmin): - list_display = ('name',) # Zeige nur den Namen des Tags - search_fields = ('name',) + + +class QivipQuizFavoriteAdmin(admin.ModelAdmin): + list_display = ('user', 'favorite', 'quiz') # Welche Felder sollen in der Übersicht angezeigt werden # Registrierung der Modelle im Admin admin.site.register(QivipQuiz, QivipQuizAdmin) admin.site.register(QivipQuestion, QivipQuestionAdmin) admin.site.register(QuizCategory, QuizCategoryAdmin) - +admin.site.register(QivipQuizFavorite, QivipQuizFavoriteAdmin) diff --git a/django/library/migrations/0035_qivipquiz_favorite.py b/django/library/migrations/0035_qivipquiz_favorite.py new file mode 100644 index 0000000..756b801 --- /dev/null +++ b/django/library/migrations/0035_qivipquiz_favorite.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.7 on 2025-04-10 14:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0034_alter_qivipquiz_status'), + ] + + operations = [ + migrations.AddField( + model_name='qivipquiz', + name='favorite', + field=models.BooleanField(default=False), + ), + ] diff --git a/django/library/migrations/0036_remove_qivipquiz_favorite_quizfavorite.py b/django/library/migrations/0036_remove_qivipquiz_favorite_quizfavorite.py new file mode 100644 index 0000000..f0efab0 --- /dev/null +++ b/django/library/migrations/0036_remove_qivipquiz_favorite_quizfavorite.py @@ -0,0 +1,32 @@ +# Generated by Django 5.1.7 on 2025-04-10 16:02 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0035_qivipquiz_favorite'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.RemoveField( + model_name='qivipquiz', + name='favorite', + ), + migrations.CreateModel( + name='QuizFavorite', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('favorite', models.BooleanField(default=False)), + ('quiz', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='library.qivipquiz')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'unique_together': {('user', 'quiz')}, + }, + ), + ] diff --git a/django/library/migrations/0037_rename_quizfavorite_qivipquizfavorite.py b/django/library/migrations/0037_rename_quizfavorite_qivipquizfavorite.py new file mode 100644 index 0000000..6eb61d5 --- /dev/null +++ b/django/library/migrations/0037_rename_quizfavorite_qivipquizfavorite.py @@ -0,0 +1,19 @@ +# Generated by Django 5.1.7 on 2025-04-10 16:05 + +from django.conf import settings +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0036_remove_qivipquiz_favorite_quizfavorite'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.RenameModel( + old_name='QuizFavorite', + new_name='QivipQuizFavorite', + ), + ] diff --git a/django/library/migrations/0038_alter_qivipquizfavorite_quiz.py b/django/library/migrations/0038_alter_qivipquizfavorite_quiz.py new file mode 100644 index 0000000..1efd121 --- /dev/null +++ b/django/library/migrations/0038_alter_qivipquizfavorite_quiz.py @@ -0,0 +1,19 @@ +# Generated by Django 5.1.7 on 2025-04-10 17:08 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0037_rename_quizfavorite_qivipquizfavorite'), + ] + + operations = [ + migrations.AlterField( + model_name='qivipquizfavorite', + name='quiz', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='favorites', to='library.qivipquiz'), + ), + ] diff --git a/django/library/models.py b/django/library/models.py index 82fcc5a..2d63668 100644 --- a/django/library/models.py +++ b/django/library/models.py @@ -43,6 +43,13 @@ class QivipQuiz(models.Model): return self.name +class QivipQuizFavorite(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) # Verknüpfung zu User + quiz = models.ForeignKey(QivipQuiz, on_delete=models.CASCADE, related_name='favorites') # Verknüpfung zu Quiz + favorite = models.BooleanField(default=False) # Favoritenstatus + + class Meta: + unique_together = ('user', 'quiz') # Sicherstellen, dass es nur ein Favorit pro User und Quiz gibt # Create your models here. diff --git a/django/library/urls.py b/django/library/urls.py index 28b2b76..1721a2b 100644 --- a/django/library/urls.py +++ b/django/library/urls.py @@ -15,5 +15,6 @@ urlpatterns = [ path('question/edit//', views.edit_question, name='edit_question'), path('question/delete//', views.delete_question, name='delete_question'), path('detail/copy//', views.copy_quiz, name='copy_quiz'), + path('favorite_quiz//', views.favorite_quiz, name='favorite_quiz'), ] diff --git a/django/library/views.py b/django/library/views.py index 5f16d54..15ba724 100644 --- a/django/library/views.py +++ b/django/library/views.py @@ -1,10 +1,11 @@ import uuid +from django.http import HttpResponse, HttpResponseRedirect 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 .models import QivipQuiz, QivipQuestion, QivipQuizFavorite from .forms import QuizForm, QuestionForm import json from django.core.paginator import Paginator @@ -17,6 +18,10 @@ from django.contrib.auth.models import User def overview_quiz(request): # Filter form = QuizFilterForm(request.GET) + + favorite_quizzes = QivipQuizFavorite.objects.filter(user=request.user, favorite=True) + favorite_quiz_ids = favorite_quizzes.values_list('quiz', flat=True) + favorite_quizzes = QivipQuiz.objects.filter(id__in=favorite_quiz_ids) # Initialize querysets if request.user.is_authenticated: @@ -82,6 +87,8 @@ def overview_quiz(request): context = { 'show_search': True, + 'favorite_quiz_ids': favorite_quiz_ids, + 'favorite_quizzes':favorite_quizzes, 'my_quizzes': my_quizzes, 'other_quizzes': other_quizzes, 'form': form, @@ -90,7 +97,21 @@ def overview_quiz(request): return render(request, 'library/overview_quiz.html', context) - +# Neues Quiz erstellen +@login_required +def favorite_quiz(request, pk): + quiz= get_object_or_404(QivipQuiz, pk=pk) + favorite = QivipQuizFavorite.objects.filter(user=request.user, quiz=quiz).first() + if favorite: + favorite.favorite=not favorite.favorite + print(favorite.favorite) + favorite.save() + + else: + QivipQuizFavorite.objects.create(user=request.user, quiz=quiz, favorite=True) + + + return redirect('library:overview_quiz') # Neues Quiz erstellen @login_required @@ -102,7 +123,7 @@ 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) + #form.save_m2m() # Speichert die Many-to-Many Beziehungen (Tags) return redirect('library:detail_quiz', pk=quiz.pk) else: diff --git a/django/templates/library/overview_quiz.html b/django/templates/library/overview_quiz.html index 955cb27..72e46e4 100644 --- a/django/templates/library/overview_quiz.html +++ b/django/templates/library/overview_quiz.html @@ -77,6 +77,7 @@
+ {% if user.is_authenticated %}
@@ -92,13 +93,40 @@
{% if quiz.image %} -
+
+ +
+
+
+ {% else %}
{% endif %} + {% if quiz.id not in favorite_quiz_ids %} +
+ + + + + + +
+ + {% else %} + + {% endif %}
+ +
@@ -228,6 +256,197 @@
{% endif %} + + + +{% if user.is_authenticated %} +
+
+

Meine Favoriten

+
+
+
+ +
+
+ {% for quiz in favorite_quizzes %} +
+ +
+ {% if quiz.image %} +
+ +
+
+
+ + + {% else %} +
+ {% endif %} + + {% if quiz.favorite == False %} + +
+ + + + + + +
+ + {% else %} + + {% endif %} +
+ + + + +
+ +

+ {{ quiz.name }} +

+ +

{{ quiz.description }}

+ + +
+ +
+ + + + {{ quiz.difficulty }} +
+ + +
+ + + + {{ quiz.questions.count }} Fragen +
+ + +
+ + + + {{ quiz.status }} +
+ + +
+ {% for i in '12345'|make_list %} + {% if forloop.counter <= quiz.average_rating|floatformat:0|add:0 %} + + {% else %} + + {% endif %} + {% endfor %} + ({{ quiz.rating_count }}) +
+
+ + + {% if quiz.authors.all %} +
+ + + + + {% for author in quiz.authors.all %} + {{ author.username }}{% if not forloop.last %}, {% endif %} + {% endfor %} + +
+ {% endif %} + + +
+ + + + + + Spielen + +
+ + + + + + + {% if quiz.user == request.user %} + + + + + + + + + + + {% endif %} +
+
+
+
+ {% endfor %} + +
+ + + {% if favorite_quizzes.paginator.num_pages > 1 %} +
+ {% if favorite_quizzes.has_previous %} + + + + + + {% endif %} + + Seite {{ favorite_quizzes.number }} von {{ favorite_quizzes.paginator.num_pages }} + + {% if my_quizzes.has_next %} + + + + + + {% endif %} +
+ {% endif %} +
+{% endif %} + + + + + + + + +
@@ -244,11 +463,37 @@
{% if quiz.image %} -
+
+ +
+
+
+ + {% else %}
{% endif %} + {% if quiz.id not in favorite_quiz_ids %} +
+ + + + + + +
+ + {% else %} + + {% endif %}
From 04ce8104fef0c7a3fef23c9fe8002f232067f196 Mon Sep 17 00:00:00 2001 From: ben8 Date: Thu, 10 Apr 2025 20:29:28 +0200 Subject: [PATCH 04/14] Fehler_behonben --- django/library/views.py | 13 +++++++++---- django/templates/library/detail_quiz.html | 3 ++- django/templates/library/overview_quiz.html | 6 +++--- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/django/library/views.py b/django/library/views.py index 15ba724..6b2a174 100644 --- a/django/library/views.py +++ b/django/library/views.py @@ -18,10 +18,15 @@ from django.contrib.auth.models import User def overview_quiz(request): # Filter form = QuizFilterForm(request.GET) - - favorite_quizzes = QivipQuizFavorite.objects.filter(user=request.user, favorite=True) - favorite_quiz_ids = favorite_quizzes.values_list('quiz', flat=True) - favorite_quizzes = QivipQuiz.objects.filter(id__in=favorite_quiz_ids) + try: + favorite_quizzes = QivipQuizFavorite.objects.filter(user=request.user, favorite=True) + favorite_quiz_ids = favorite_quizzes.values_list('quiz', flat=True) + favorite_quizzes = QivipQuiz.objects.filter(id__in=favorite_quiz_ids) + except: + favorite_quizzes = QivipQuizFavorite.objects.none() + favorite_quiz_ids = favorite_quizzes.none() + favorite_quizzes = QivipQuiz.objects.none() + # Initialize querysets if request.user.is_authenticated: diff --git a/django/templates/library/detail_quiz.html b/django/templates/library/detail_quiz.html index 06ec9e7..17afbc8 100644 --- a/django/templates/library/detail_quiz.html +++ b/django/templates/library/detail_quiz.html @@ -22,8 +22,9 @@ -
{% endif %} +
+
diff --git a/django/templates/library/overview_quiz.html b/django/templates/library/overview_quiz.html index 72e46e4..a66677c 100644 --- a/django/templates/library/overview_quiz.html +++ b/django/templates/library/overview_quiz.html @@ -93,7 +93,7 @@
{% if quiz.image %} -
+
@@ -274,7 +274,7 @@
{% if quiz.image %} -
+
@@ -463,7 +463,7 @@
{% if quiz.image %} -
+
From 2a7e39bbd053d07e6709f07babfb89b769aee8e9 Mon Sep 17 00:00:00 2001 From: ben8 Date: Fri, 11 Apr 2025 18:18:34 +0200 Subject: [PATCH 05/14] Favoritenfunktion! #55 --- .../0039_qivipquizfavorite_favorite_date.py | 18 +++++ .../0040_alter_qivipquiz_description.py | 19 +++++ ...ory_alter_qivipquiz_difficulty_and_more.py | 34 +++++++++ .../migrations/0042_qivipquiz_favorite.py | 19 +++++ .../0043_remove_qivipquiz_favorite.py | 17 +++++ ...ivipquizfavorite_favorite_date_and_more.py | 22 ++++++ django/library/models.py | 12 +-- django/library/views.py | 76 +++++++++++++++++-- django/templates/library/overview_quiz.html | 15 ++++ 9 files changed, 220 insertions(+), 12 deletions(-) create mode 100644 django/library/migrations/0039_qivipquizfavorite_favorite_date.py create mode 100644 django/library/migrations/0040_alter_qivipquiz_description.py create mode 100644 django/library/migrations/0041_alter_qivipquiz_category_alter_qivipquiz_difficulty_and_more.py create mode 100644 django/library/migrations/0042_qivipquiz_favorite.py create mode 100644 django/library/migrations/0043_remove_qivipquiz_favorite.py create mode 100644 django/library/migrations/0044_remove_qivipquizfavorite_favorite_date_and_more.py diff --git a/django/library/migrations/0039_qivipquizfavorite_favorite_date.py b/django/library/migrations/0039_qivipquizfavorite_favorite_date.py new file mode 100644 index 0000000..a4eb4d8 --- /dev/null +++ b/django/library/migrations/0039_qivipquizfavorite_favorite_date.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.7 on 2025-04-11 12:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0038_alter_qivipquizfavorite_quiz'), + ] + + operations = [ + migrations.AddField( + model_name='qivipquizfavorite', + name='favorite_date', + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/django/library/migrations/0040_alter_qivipquiz_description.py b/django/library/migrations/0040_alter_qivipquiz_description.py new file mode 100644 index 0000000..16ac3b0 --- /dev/null +++ b/django/library/migrations/0040_alter_qivipquiz_description.py @@ -0,0 +1,19 @@ +# Generated by Django 5.1.7 on 2025-04-11 13:15 + +import library.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0039_qivipquizfavorite_favorite_date'), + ] + + operations = [ + migrations.AlterField( + model_name='qivipquiz', + name='description', + field=models.TextField(default='In dem Quiz geht es um ...', max_length=200, validators=[library.models.QivipQuiz.validate_description], verbose_name='Beschreibung'), + ), + ] diff --git a/django/library/migrations/0041_alter_qivipquiz_category_alter_qivipquiz_difficulty_and_more.py b/django/library/migrations/0041_alter_qivipquiz_category_alter_qivipquiz_difficulty_and_more.py new file mode 100644 index 0000000..32fee6b --- /dev/null +++ b/django/library/migrations/0041_alter_qivipquiz_category_alter_qivipquiz_difficulty_and_more.py @@ -0,0 +1,34 @@ +# Generated by Django 5.1.7 on 2025-04-11 13:21 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0040_alter_qivipquiz_description'), + ] + + operations = [ + migrations.AlterField( + model_name='qivipquiz', + name='category', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='quiz', to='library.quizcategory', verbose_name='Kategorie'), + ), + migrations.AlterField( + model_name='qivipquiz', + name='difficulty', + field=models.CharField(choices=[('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('nicht gesetzt', 'nicht gesetzt')], default='nicht gesetzt', help_text='1: niedrigste Schwierigkeit und 5: höchste Schwierigkeit', max_length=13, verbose_name='Schwierigkeit'), + ), + migrations.AlterField( + model_name='qivipquiz', + name='image', + field=models.ImageField(blank=True, max_length=256, null=True, upload_to='quiz_images/', verbose_name='Bild'), + ), + migrations.AlterField( + model_name='qivipquiz', + name='name', + field=models.CharField(max_length=75, verbose_name='Name des Quizzes'), + ), + ] diff --git a/django/library/migrations/0042_qivipquiz_favorite.py b/django/library/migrations/0042_qivipquiz_favorite.py new file mode 100644 index 0000000..9913a85 --- /dev/null +++ b/django/library/migrations/0042_qivipquiz_favorite.py @@ -0,0 +1,19 @@ +# Generated by Django 5.1.7 on 2025-04-11 13:43 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0041_alter_qivipquiz_category_alter_qivipquiz_difficulty_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='qivipquiz', + name='favorite', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quizzes', to='library.qivipquizfavorite'), + ), + ] diff --git a/django/library/migrations/0043_remove_qivipquiz_favorite.py b/django/library/migrations/0043_remove_qivipquiz_favorite.py new file mode 100644 index 0000000..f7dfdfc --- /dev/null +++ b/django/library/migrations/0043_remove_qivipquiz_favorite.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1.7 on 2025-04-11 15:25 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0042_qivipquiz_favorite'), + ] + + operations = [ + migrations.RemoveField( + model_name='qivipquiz', + name='favorite', + ), + ] diff --git a/django/library/migrations/0044_remove_qivipquizfavorite_favorite_date_and_more.py b/django/library/migrations/0044_remove_qivipquizfavorite_favorite_date_and_more.py new file mode 100644 index 0000000..c3df207 --- /dev/null +++ b/django/library/migrations/0044_remove_qivipquizfavorite_favorite_date_and_more.py @@ -0,0 +1,22 @@ +# Generated by Django 5.1.7 on 2025-04-11 16:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0043_remove_qivipquiz_favorite'), + ] + + operations = [ + migrations.RemoveField( + model_name='qivipquizfavorite', + name='favorite_date', + ), + migrations.AddField( + model_name='qivipquiz', + name='favorite_date', + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/django/library/models.py b/django/library/models.py index 2d63668..b1769b0 100644 --- a/django/library/models.py +++ b/django/library/models.py @@ -24,7 +24,7 @@ class QivipQuiz(models.Model): if value.strip() == "In dem Quiz geht es um ...": raise ValidationError("Bitte gib eine aussagekräftige Beschreibung ein.") - image = models.ImageField(max_length=256, upload_to='quiz_images/', blank=True, null=True) # Bild speichern in media/quiz_images/ + image = models.ImageField(max_length=256,verbose_name="Bild", upload_to='quiz_images/', blank=True, null=True) # Bild speichern in media/quiz_images/ uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) user_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name='quiz') #creator = models.ForeignKey(User, on_delete=models.SET_NULL,blank=True, null=True, related_name='creator_quiz') @@ -32,13 +32,14 @@ class QivipQuiz(models.Model): creation_date = models.DateTimeField(auto_now_add=True) update_date = models.DateTimeField(auto_now=True) status = models.CharField(max_length=10, choices=list(STATUS_VALUES.items()), default="öffentlich") - category = models.ForeignKey('QuizCategory', related_name='quiz', on_delete=models.CASCADE) - name = models.CharField(max_length=75) - description = models.TextField(validators=[validate_description],max_length=200,blank=False, default="In dem Quiz geht es um ...") - difficulty= models.CharField(max_length=13, choices=list(DIFFICULTY_VALUES.items()), default="nicht gesetzt", help_text="1: niedrigste Schwierigkeit und 5: höchste Schwierigkeit") + category = models.ForeignKey('QuizCategory',verbose_name="Kategorie", related_name='quiz', on_delete=models.CASCADE) + name = models.CharField(max_length=75,verbose_name="Name des Quizzes") + description = models.TextField(validators=[validate_description],max_length=200,blank=False, default="In dem Quiz geht es um ...", verbose_name="Beschreibung") + difficulty= models.CharField(verbose_name="Schwierigkeit", max_length=13, choices=list(DIFFICULTY_VALUES.items()), default="nicht gesetzt", help_text="1: niedrigste Schwierigkeit und 5: höchste Schwierigkeit") credits=models.TextField(blank=True, editable=True) average_rating = models.FloatField(default=3.0) rating_count = models.IntegerField(default=0) + favorite_date=models.DateTimeField(auto_now=True) def __str__(self): return self.name @@ -47,6 +48,7 @@ class QivipQuizFavorite(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) # Verknüpfung zu User quiz = models.ForeignKey(QivipQuiz, on_delete=models.CASCADE, related_name='favorites') # Verknüpfung zu Quiz favorite = models.BooleanField(default=False) # Favoritenstatus + class Meta: unique_together = ('user', 'quiz') # Sicherstellen, dass es nur ein Favorit pro User und Quiz gibt diff --git a/django/library/views.py b/django/library/views.py index 6b2a174..565709e 100644 --- a/django/library/views.py +++ b/django/library/views.py @@ -19,20 +19,22 @@ def overview_quiz(request): # Filter form = QuizFilterForm(request.GET) try: - favorite_quizzes = QivipQuizFavorite.objects.filter(user=request.user, favorite=True) - favorite_quiz_ids = favorite_quizzes.values_list('quiz', flat=True) + favorite_quizzes_data = QivipQuizFavorite.objects.filter(user=request.user, favorite=True) + favorite_quiz_ids = favorite_quizzes_data.values_list('quiz', flat=True) favorite_quizzes = QivipQuiz.objects.filter(id__in=favorite_quiz_ids) except: + favorite_quizzes_data = QivipQuizFavorite.objects.none() favorite_quizzes = QivipQuizFavorite.objects.none() favorite_quiz_ids = favorite_quizzes.none() favorite_quizzes = QivipQuiz.objects.none() - # Initialize querysets if request.user.is_authenticated: filter_my_quizzes = QivipQuiz.objects.filter(user_id=request.user).annotate(max_amout_questions=Count('questions')) + favorite_quizzes = QivipQuiz.objects.filter(id__in=favorite_quiz_ids).annotate(max_amout_questions=Count('questions')) filter_other_quizzes = QivipQuiz.objects.exclude(user_id=request.user) else: + favorite_quizzes = QivipQuiz.objects.none() filter_my_quizzes = QivipQuiz.objects.none() filter_other_quizzes = QivipQuiz.objects.all() @@ -40,11 +42,49 @@ def overview_quiz(request): filter_other_quizzes = filter_other_quizzes.annotate(max_amout_questions=Count('questions')) filter_other_quizzes = filter_other_quizzes.filter(max_amout_questions__gte=1, status='öffentlich') + + + + 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') + + filters = {} + if username: + try: + user = User.objects.get(username=username) + filters['user_id'] = user.id + except User.DoesNotExist: + favorite_quizzes = QivipQuiz.objects.none() + filter_my_quizzes = QivipQuiz.objects.none() + filter_other_quizzes=QivipQuiz.objects.none() + + if search: + filters['name__icontains'] = search + if min_amout_questions: + filters['max_amout_questions__gte'] = min_amout_questions + if max_amout_questions: + filters['max_amout_questions__lte'] = max_amout_questions + + try: + filter_other_quizzes = filter_other_quizzes.filter(**filters) + except: + filter_other_quizzes=QivipQuiz.objects.none() + try: + filter_my_quizzes = filter_my_quizzes.filter(**filters) + except: + filter_my_quizzes=QivipQuiz.objects.none() + + try: + favorite_quizzes = favorite_quizzes.filter(**filters) + except: + favorite_quizzes=QivipQuiz.objects.none() + + """ 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) @@ -73,9 +113,9 @@ def overview_quiz(request): filter_other_quizzes=filter_other_quizzes.exclude(user_id=request.user) except: filter_other_quizzes=filter_other_quizzes + """ - # Pagination for my quizzes my_quizzes_paginator = Paginator(filter_my_quizzes.order_by('-creation_date'), 8) # 8 quizzes per page try: @@ -90,6 +130,19 @@ def overview_quiz(request): except: other_quizzes = other_quizzes_paginator.page(1) + + + + + + + # Pagination for favorite_quizzes + favorite_quizzes_paginator = Paginator(favorite_quizzes.order_by("-favorite_date"), 8) # 8 quizzes per page + try: + favorite_quizzes = favorite_quizzes_paginator.page(request.GET.get('my_page', 1)) + except: + favorite_quizzes = favorite_quizzes_paginator.page(1) + context = { 'show_search': True, 'favorite_quiz_ids': favorite_quiz_ids, @@ -100,23 +153,32 @@ def overview_quiz(request): } return render(request, 'library/overview_quiz.html', context) - # Neues Quiz erstellen @login_required def favorite_quiz(request, pk): quiz= get_object_or_404(QivipQuiz, pk=pk) favorite = QivipQuizFavorite.objects.filter(user=request.user, quiz=quiz).first() + if favorite: favorite.favorite=not favorite.favorite - print(favorite.favorite) + favorite.save() + + if favorite.favorite==True: + quiz.save(update_fields=['favorite_date']) + statement="Das Quiz '"+ favorite.quiz.name+ "' wurde erfolgreich zu den Favoriten hinzugefügt!" + messages.success(request,statement ) + else: + statement="Das Quiz '"+ favorite.quiz.name+ "' wurde erfolgreich von den Favoriten entfernt!" + messages.error(request, statement) + else: QivipQuizFavorite.objects.create(user=request.user, quiz=quiz, favorite=True) - return redirect('library:overview_quiz') + return redirect(request.META.get('HTTP_REFERER', 'library:overview_quiz')) # Neues Quiz erstellen @login_required diff --git a/django/templates/library/overview_quiz.html b/django/templates/library/overview_quiz.html index a66677c..7a420cd 100644 --- a/django/templates/library/overview_quiz.html +++ b/django/templates/library/overview_quiz.html @@ -619,5 +619,20 @@ document.addEventListener('DOMContentLoaded', function() { document.getElementById('filterPanel').classList.toggle('show'); }); }); + +if (window.location.pathname === "/library/") { + window.addEventListener("beforeunload", function () { + localStorage.setItem("meine_seite_scroll", window.scrollY); + }); + + window.addEventListener("load", function () { + const scrollPos = localStorage.getItem("meine_seite_scroll"); + if (scrollPos !== null) { + window.scrollTo(0, parseInt(scrollPos)); + } + }); +} + + {% endblock content %} From 1f3b551b9470b9c7326fd72d40ccbd06706c1f89 Mon Sep 17 00:00:00 2001 From: ben8 Date: Fri, 11 Apr 2025 19:31:12 +0200 Subject: [PATCH 06/14] Favoriten --- ...remove_qivipquiz_favorite_date_and_more.py | 22 +++++++++++++++++++ ...6_alter_qivipquizfavorite_favorite_date.py | 18 +++++++++++++++ django/library/models.py | 3 +-- django/library/views.py | 18 +++++++++------ 4 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 django/library/migrations/0045_remove_qivipquiz_favorite_date_and_more.py create mode 100644 django/library/migrations/0046_alter_qivipquizfavorite_favorite_date.py diff --git a/django/library/migrations/0045_remove_qivipquiz_favorite_date_and_more.py b/django/library/migrations/0045_remove_qivipquiz_favorite_date_and_more.py new file mode 100644 index 0000000..8d92ed4 --- /dev/null +++ b/django/library/migrations/0045_remove_qivipquiz_favorite_date_and_more.py @@ -0,0 +1,22 @@ +# Generated by Django 5.1.7 on 2025-04-11 16:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0044_remove_qivipquizfavorite_favorite_date_and_more'), + ] + + operations = [ + migrations.RemoveField( + model_name='qivipquiz', + name='favorite_date', + ), + migrations.AddField( + model_name='qivipquizfavorite', + name='favorite_date', + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/django/library/migrations/0046_alter_qivipquizfavorite_favorite_date.py b/django/library/migrations/0046_alter_qivipquizfavorite_favorite_date.py new file mode 100644 index 0000000..e08ca9d --- /dev/null +++ b/django/library/migrations/0046_alter_qivipquizfavorite_favorite_date.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.7 on 2025-04-11 16:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('library', '0045_remove_qivipquiz_favorite_date_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='qivipquizfavorite', + name='favorite_date', + field=models.DateTimeField(blank=True, null=True), + ), + ] diff --git a/django/library/models.py b/django/library/models.py index b1769b0..1477a3d 100644 --- a/django/library/models.py +++ b/django/library/models.py @@ -39,7 +39,6 @@ class QivipQuiz(models.Model): credits=models.TextField(blank=True, editable=True) average_rating = models.FloatField(default=3.0) rating_count = models.IntegerField(default=0) - favorite_date=models.DateTimeField(auto_now=True) def __str__(self): return self.name @@ -48,7 +47,7 @@ class QivipQuizFavorite(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) # Verknüpfung zu User quiz = models.ForeignKey(QivipQuiz, on_delete=models.CASCADE, related_name='favorites') # Verknüpfung zu Quiz favorite = models.BooleanField(default=False) # Favoritenstatus - + favorite_date = models.DateTimeField(null=True, blank=True) class Meta: unique_together = ('user', 'quiz') # Sicherstellen, dass es nur ein Favorit pro User und Quiz gibt diff --git a/django/library/views.py b/django/library/views.py index 565709e..7baeef4 100644 --- a/django/library/views.py +++ b/django/library/views.py @@ -1,3 +1,4 @@ +from django.utils import timezone import uuid from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import render, redirect, get_object_or_404 @@ -19,7 +20,7 @@ def overview_quiz(request): # Filter form = QuizFilterForm(request.GET) try: - favorite_quizzes_data = QivipQuizFavorite.objects.filter(user=request.user, favorite=True) + favorite_quizzes_data = QivipQuizFavorite.objects.filter(user=request.user, favorite=True).order_by("-favorite_date") favorite_quiz_ids = favorite_quizzes_data.values_list('quiz', flat=True) favorite_quizzes = QivipQuiz.objects.filter(id__in=favorite_quiz_ids) except: @@ -31,7 +32,7 @@ def overview_quiz(request): # Initialize querysets if request.user.is_authenticated: filter_my_quizzes = QivipQuiz.objects.filter(user_id=request.user).annotate(max_amout_questions=Count('questions')) - favorite_quizzes = QivipQuiz.objects.filter(id__in=favorite_quiz_ids).annotate(max_amout_questions=Count('questions')) + favorite_quizzes = favorite_quizzes.filter(id__in=favorite_quiz_ids).annotate(max_amout_questions=Count('questions')) filter_other_quizzes = QivipQuiz.objects.exclude(user_id=request.user) else: favorite_quizzes = QivipQuiz.objects.none() @@ -137,7 +138,7 @@ def overview_quiz(request): # Pagination for favorite_quizzes - favorite_quizzes_paginator = Paginator(favorite_quizzes.order_by("-favorite_date"), 8) # 8 quizzes per page + favorite_quizzes_paginator = Paginator(favorite_quizzes, 8) # 8 quizzes per page try: favorite_quizzes = favorite_quizzes_paginator.page(request.GET.get('my_page', 1)) except: @@ -163,19 +164,22 @@ def favorite_quiz(request, pk): if favorite: favorite.favorite=not favorite.favorite - favorite.save() + if favorite.favorite==True: - quiz.save(update_fields=['favorite_date']) + favorite.favorite_date = timezone.now() + statement="Das Quiz '"+ favorite.quiz.name+ "' wurde erfolgreich zu den Favoriten hinzugefügt!" messages.success(request,statement ) else: + favorite.favorite_date = None + statement="Das Quiz '"+ favorite.quiz.name+ "' wurde erfolgreich von den Favoriten entfernt!" messages.error(request, statement) - + favorite.save() else: - QivipQuizFavorite.objects.create(user=request.user, quiz=quiz, favorite=True) + QivipQuizFavorite.objects.create(user=request.user, quiz=quiz, favorite=True, favorite_date=timezone.now()) return redirect(request.META.get('HTTP_REFERER', 'library:overview_quiz')) From d53240c710050ba1370e165b1d25ca240a2a2c47 Mon Sep 17 00:00:00 2001 From: ben8 Date: Fri, 11 Apr 2025 20:29:55 +0200 Subject: [PATCH 07/14] Favoriten_nur_wenn_angemeldet! --- django/library/views.py | 11 +++++++++-- django/templates/library/overview_quiz.html | 11 ++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/django/library/views.py b/django/library/views.py index 7baeef4..fabbcff 100644 --- a/django/library/views.py +++ b/django/library/views.py @@ -180,10 +180,17 @@ def favorite_quiz(request, pk): favorite.save() else: QivipQuizFavorite.objects.create(user=request.user, quiz=quiz, favorite=True, favorite_date=timezone.now()) - - + """ + referer = request.META.get('HTTP_REFERER') + if referer and 'library/' in referer: + + return redirect(request.META.get('HTTP_REFERER', 'library:overview_quiz')) + else: + return overview_quiz(request) + """ return redirect(request.META.get('HTTP_REFERER', 'library:overview_quiz')) + # Neues Quiz erstellen @login_required def new_quiz(request): diff --git a/django/templates/library/overview_quiz.html b/django/templates/library/overview_quiz.html index 7a420cd..4c27130 100644 --- a/django/templates/library/overview_quiz.html +++ b/django/templates/library/overview_quiz.html @@ -104,6 +104,7 @@ {% else %}
{% endif %} + {% if user.is_authenticated %} {% if quiz.id not in favorite_quiz_ids %}
@@ -123,6 +124,7 @@
{% endif %} + {% endif %}
@@ -207,7 +209,7 @@
- {% if quiz.user == request.user %} + {% if quiz.user_id == request.user %} @@ -285,7 +287,7 @@ {% else %}
{% endif %} - + {% if user.is_authenticated %} {% if quiz.favorite == False %}
{% endif %} + {% endif %}
@@ -390,7 +393,7 @@ - {% if quiz.user == request.user %} + {% if quiz.user_id == request.user %} @@ -475,6 +478,7 @@ {% else %}
{% endif %} + {% if user.is_authenticated %} {% if quiz.id not in favorite_quiz_ids %}
{% endif %} + {% endif %}
From 5f05964b1b37abf0192bb80c89974e9580371a5d Mon Sep 17 00:00:00 2001 From: ben8 Date: Sun, 13 Apr 2025 13:09:39 +0200 Subject: [PATCH 08/14] =?UTF-8?q?Suchleiste=5F=C3=BCberall=20#96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- django/templates/partials/_nav.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/django/templates/partials/_nav.html b/django/templates/partials/_nav.html index 60f8a6f..1b0cc9a 100644 --- a/django/templates/partials/_nav.html +++ b/django/templates/partials/_nav.html @@ -5,8 +5,8 @@
- {% if show_search %} -
+ +
- {% endif %} +
    From a59df8dd62373dc3d42f1d73e510e5fa05658f01 Mon Sep 17 00:00:00 2001 From: ben8 Date: Sun, 13 Apr 2025 17:01:28 +0200 Subject: [PATCH 09/14] #98 plus besser Darstellung der Suchleiste --- django/templates/partials/_nav.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/django/templates/partials/_nav.html b/django/templates/partials/_nav.html index 1b0cc9a..c73f2b8 100644 --- a/django/templates/partials/_nav.html +++ b/django/templates/partials/_nav.html @@ -1,23 +1,23 @@ -