From e135ff945f8cb5a98ca300f294d3290739b961f7 Mon Sep 17 00:00:00 2001
From: nik8
Date: Sat, 5 Apr 2025 12:07:56 +0200
Subject: [PATCH] Kopie eines Quizzes (Datenbank)
---
django/library/admin.py | 1 -
django/library/forms.py | 2 +-
.../0025_qivipquiz_modified_description.py | 18 ++++
...26_alter_qivipquiz_modified_description.py | 18 ++++
.../migrations/0027_qivipquiz_creator.py | 21 +++++
.../0028_alter_qivipquiz_creator.py | 21 +++++
.../migrations/0029_qivipquiz_credits.py | 18 ++++
.../0030_remove_qivipquiz_creator_and_more.py | 27 ++++++
django/library/models.py | 6 +-
django/library/urls.py | 2 +
django/library/views.py | 84 +++++++++++++++++--
django/templates/library/detail_quiz.html | 47 ++++++++---
django/templates/library/overview_quiz.html | 18 +++-
13 files changed, 259 insertions(+), 24 deletions(-)
create mode 100644 django/library/migrations/0025_qivipquiz_modified_description.py
create mode 100644 django/library/migrations/0026_alter_qivipquiz_modified_description.py
create mode 100644 django/library/migrations/0027_qivipquiz_creator.py
create mode 100644 django/library/migrations/0028_alter_qivipquiz_creator.py
create mode 100644 django/library/migrations/0029_qivipquiz_credits.py
create mode 100644 django/library/migrations/0030_remove_qivipquiz_creator_and_more.py
diff --git a/django/library/admin.py b/django/library/admin.py
index 14c0c5b..4c7eda2 100644
--- a/django/library/admin.py
+++ b/django/library/admin.py
@@ -6,7 +6,6 @@ class QivipQuizAdmin(admin.ModelAdmin):
list_display = ('name', '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
class QivipQuestionAdmin(admin.ModelAdmin):
list_display = ('quiz_id', 'data', 'creation_date', 'update_date')
diff --git a/django/library/forms.py b/django/library/forms.py
index 4ca84f8..c454b71 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"]
+ fields = ['name', 'description','image', 'status', 'category', 'tags',"difficulty","credits"]
class QuestionForm(forms.ModelForm):
class Meta:
diff --git a/django/library/migrations/0025_qivipquiz_modified_description.py b/django/library/migrations/0025_qivipquiz_modified_description.py
new file mode 100644
index 0000000..603c205
--- /dev/null
+++ b/django/library/migrations/0025_qivipquiz_modified_description.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.1.7 on 2025-04-03 16:46
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('library', '0024_alter_qivipquiz_image'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='qivipquiz',
+ name='modified_description',
+ field=models.TextField(blank=True, default='Das Quiz wurde modifiziert von:', editable=False),
+ ),
+ ]
diff --git a/django/library/migrations/0026_alter_qivipquiz_modified_description.py b/django/library/migrations/0026_alter_qivipquiz_modified_description.py
new file mode 100644
index 0000000..0dd27b6
--- /dev/null
+++ b/django/library/migrations/0026_alter_qivipquiz_modified_description.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.1.7 on 2025-04-04 13:28
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('library', '0025_qivipquiz_modified_description'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='qivipquiz',
+ name='modified_description',
+ field=models.TextField(blank=True, editable=False),
+ ),
+ ]
diff --git a/django/library/migrations/0027_qivipquiz_creator.py b/django/library/migrations/0027_qivipquiz_creator.py
new file mode 100644
index 0000000..5d99ae1
--- /dev/null
+++ b/django/library/migrations/0027_qivipquiz_creator.py
@@ -0,0 +1,21 @@
+# Generated by Django 5.1.7 on 2025-04-04 13:37
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('library', '0026_alter_qivipquiz_modified_description'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='qivipquiz',
+ name='creator',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='creator_quiz', to=settings.AUTH_USER_MODEL),
+ ),
+ ]
diff --git a/django/library/migrations/0028_alter_qivipquiz_creator.py b/django/library/migrations/0028_alter_qivipquiz_creator.py
new file mode 100644
index 0000000..b3e7941
--- /dev/null
+++ b/django/library/migrations/0028_alter_qivipquiz_creator.py
@@ -0,0 +1,21 @@
+# Generated by Django 5.1.7 on 2025-04-04 13:57
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('library', '0027_qivipquiz_creator'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='qivipquiz',
+ name='creator',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='creator_quiz', to=settings.AUTH_USER_MODEL),
+ ),
+ ]
diff --git a/django/library/migrations/0029_qivipquiz_credits.py b/django/library/migrations/0029_qivipquiz_credits.py
new file mode 100644
index 0000000..7b4e8fd
--- /dev/null
+++ b/django/library/migrations/0029_qivipquiz_credits.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.1.7 on 2025-04-04 16:02
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('library', '0028_alter_qivipquiz_creator'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='qivipquiz',
+ name='credits',
+ field=models.TextField(blank=True),
+ ),
+ ]
diff --git a/django/library/migrations/0030_remove_qivipquiz_creator_and_more.py b/django/library/migrations/0030_remove_qivipquiz_creator_and_more.py
new file mode 100644
index 0000000..0401baa
--- /dev/null
+++ b/django/library/migrations/0030_remove_qivipquiz_creator_and_more.py
@@ -0,0 +1,27 @@
+# Generated by Django 5.1.7 on 2025-04-05 09:39
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('library', '0029_qivipquiz_credits'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='qivipquiz',
+ name='creator',
+ ),
+ migrations.RemoveField(
+ model_name='qivipquiz',
+ name='modified_description',
+ ),
+ migrations.AddField(
+ model_name='qivipquiz',
+ name='base_quiz',
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='child_quizzes', to='library.qivipquiz'),
+ ),
+ ]
diff --git a/django/library/models.py b/django/library/models.py
index a35d6d9..f49d071 100644
--- a/django/library/models.py
+++ b/django/library/models.py
@@ -27,6 +27,8 @@ class QivipQuiz(models.Model):
image = models.ImageField(max_length=256, 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')
+ base_quiz = models.ForeignKey('self', on_delete=models.SET_NULL,blank=True, null=True, related_name='child_quizzes')
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")
@@ -35,11 +37,13 @@ class QivipQuiz(models.Model):
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")
-
+ credits=models.TextField(blank=True, editable=True)
def __str__(self):
+
return self.name
+
# Create your models here.
class QivipQuestion(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
diff --git a/django/library/urls.py b/django/library/urls.py
index 45d780c..befd359 100644
--- a/django/library/urls.py
+++ b/django/library/urls.py
@@ -14,6 +14,8 @@ urlpatterns = [
path('question/new/', views.new_question, name='new_question'),
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'),
+
]# Nur für die Entwicklungsumgebung
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
diff --git a/django/library/views.py b/django/library/views.py
index cd95d07..b947631 100644
--- a/django/library/views.py
+++ b/django/library/views.py
@@ -1,3 +1,4 @@
+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
@@ -26,7 +27,6 @@ def overview_quiz(request):
filter_my_quizzes = QivipQuiz.objects.none()
filter_other_quizzes = QivipQuiz.objects.annotate(max_amout_questions=Count('question'))
-
@@ -67,13 +67,14 @@ def overview_quiz(request):
except:
filter_other_quizzes=filter_other_quizzes
- # Anzahl der Quiz pro Seite für Swiper
- print("kein Filter ,form_valid")
+
+ 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,
- 'filter_other_quizzes': filter_other_quizzes,
+ 'filter_my_quizzes': filter_my_quizzes.order_by('-creation_date'),
+ 'filter_other_quizzes': filter_other_quizzes.order_by('-creation_date'),
'form': form,
}
@@ -91,6 +92,7 @@ def new_quiz(request):
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)
@@ -106,12 +108,15 @@ def edit_quiz(request, pk):
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=quiz.pk)
+ 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):
@@ -122,9 +127,9 @@ def delete_quiz(request, pk):
return render(request, 'library/delete_confirmation.html', {'object': quiz})
# Quiz anzeigen
-@login_required
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, 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
@@ -137,6 +142,63 @@ def detail_quiz(request, pk):
'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
@@ -212,6 +274,7 @@ def new_question(request):
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
@@ -340,7 +403,9 @@ def edit_question(request, pk):
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 = {
@@ -351,6 +416,7 @@ def edit_question(request, pk):
return render(request, template_name, context)
+
# Frage löschen
@login_required
def delete_question(request, pk):
diff --git a/django/templates/library/detail_quiz.html b/django/templates/library/detail_quiz.html
index e6736ef..9120802 100644
--- a/django/templates/library/detail_quiz.html
+++ b/django/templates/library/detail_quiz.html
@@ -1,10 +1,13 @@
{% extends 'base.html' %}
{% block content %}
+
+
{% if quiz.description %}
-
{{ quiz.description }}
+
{{ quiz.description }}
{% endif %}
+
+
Fragen
+ {% if quiz.user_id == request.user %}
Multiple Choice
+ {% endif %}
+ {% if quiz.user_id == request.user %}
Wahr/Falsch
+ {% endif %}
@@ -46,7 +58,7 @@
{% for question in questions %}
{% endif %}
+
+
+
+ {% if quiz.base_quiz %}
+
Autor: {{ quiz.base_quiz.user_id}}
+ {% endif %}
+
+
+
+ {% if quiz.credits %}
+
Credits: {{ quiz.credits }}
+ {% endif %}
+
+
{% endblock %}
diff --git a/django/templates/library/overview_quiz.html b/django/templates/library/overview_quiz.html
index c5c66da..0cb1313 100644
--- a/django/templates/library/overview_quiz.html
+++ b/django/templates/library/overview_quiz.html
@@ -68,6 +68,19 @@
Schwierigkeit: {{ quiz.difficulty }}
Anzahl der Fragen: {{ quiz.question.count }}
Status: {{ quiz.status }}
+
+
+
+ {% if quiz.authors.all %}
+ Autor(en):
+ {% for author in quiz.authors.all %}
+
+ {{ author.username }}{% if not forloop.last %}, {% endif %}
+ {% endfor %}
+
+ {% endif %}
+
+
@@ -126,6 +139,9 @@
Anzahl der Fragen: {{ quiz.question.count }}
Erstellt am: {{ quiz.creation_date }}
+ {% if quiz.original_creator %}
+ Ursprünglich erstellt von: {{ quiz.original_creator }}
+ {% endif %}