From d03d3b48d41110b34816e3fdcc9d1b2c365afbb7 Mon Sep 17 00:00:00 2001
From: "Edgar P. Burkhart"
Date: Sun, 15 Jun 2025 12:40:55 +0200
Subject: [PATCH] Add game answer functionality with form and view for user
responses
---
base/static/css/main.css | 4 +++
game/forms.py | 19 ++++++++++++
game/migrations/0018_musicgameanswer.py | 10 +++---
game/models.py | 9 ++----
.../templates/game/include/group_members.html | 2 +-
game/templates/game/musikgame_answer.html | 26 ++++++++++++++++
game/templates/game/musikgame_detail.html | 3 ++
game/urls.py | 5 +++
game/views.py | 31 +++++++++++++++++++
9 files changed, 97 insertions(+), 12 deletions(-)
create mode 100644 game/templates/game/musikgame_answer.html
diff --git a/base/static/css/main.css b/base/static/css/main.css
index c6146bc..90e5032 100644
--- a/base/static/css/main.css
+++ b/base/static/css/main.css
@@ -130,3 +130,7 @@ td.c, th.c {
margin: 0;
}
}
+
+table select {
+ margin-bottom: 0;
+}
diff --git a/game/forms.py b/game/forms.py
index 76dec01..c90e286 100644
--- a/game/forms.py
+++ b/game/forms.py
@@ -39,3 +39,22 @@ class MusikGameForm(forms.ModelForm):
kwargs["initial"].setdefault("players", players)
super().__init__(*args, **kwargs)
self.fields["players"].queryset = players
+
+
+class AnswerForm(forms.Form):
+ def __init__(self, *args, **kwargs):
+ game = kwargs.pop("game")
+ user = kwargs.pop("user")
+ super().__init__(*args, **kwargs)
+
+ for music in game.musicgameorder_set.all():
+ self.fields[f"answer-{music.order}"] = forms.ChoiceField(
+ choices=[("", "")]
+ + list(game.players.all().values_list("id", "username")),
+ required=False,
+ label=music.order,
+ initial=ma.answer.id
+ if (ma := music.musicgameanswer_set.filter(player=user).first())
+ and ma.answer
+ else "",
+ )
diff --git a/game/migrations/0018_musicgameanswer.py b/game/migrations/0018_musicgameanswer.py
index c1d8503..1f760be 100644
--- a/game/migrations/0018_musicgameanswer.py
+++ b/game/migrations/0018_musicgameanswer.py
@@ -1,4 +1,4 @@
-# Generated by Django 5.2.3 on 2025-06-15 09:56
+# Generated by Django 5.2.3 on 2025-06-15 10:36
import django.db.models.deletion
from django.conf import settings
@@ -24,7 +24,6 @@ class Migration(migrations.Migration):
verbose_name="ID",
),
),
- ("order", models.PositiveIntegerField()),
(
"answer",
models.ForeignKey(
@@ -37,7 +36,8 @@ class Migration(migrations.Migration):
(
"game",
models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE, to="game.musikgame"
+ on_delete=django.db.models.deletion.CASCADE,
+ to="game.musicgameorder",
),
),
(
@@ -49,10 +49,10 @@ class Migration(migrations.Migration):
),
],
options={
- "ordering": ["order"],
+ "ordering": ["game"],
"constraints": [
models.UniqueConstraint(
- fields=("game", "player", "order"), name="unique_answer"
+ fields=("game", "player"), name="unique_answer"
)
],
},
diff --git a/game/models.py b/game/models.py
index 99a5d6b..6f4e672 100644
--- a/game/models.py
+++ b/game/models.py
@@ -114,17 +114,14 @@ class MusicGameOrder(models.Model):
class MusicGameAnswer(models.Model):
- game = models.ForeignKey(MusikGame, on_delete=models.CASCADE)
+ game = models.ForeignKey(MusicGameOrder, on_delete=models.CASCADE)
player = models.ForeignKey(User, on_delete=models.CASCADE)
- order = models.PositiveIntegerField()
answer = models.ForeignKey(
User, on_delete=models.SET_NULL, null=True, related_name="+"
)
class Meta:
constraints = [
- models.UniqueConstraint(
- fields=("game", "player", "order"), name="unique_answer"
- ),
+ models.UniqueConstraint(fields=("game", "player"), name="unique_answer"),
]
- ordering = ["order"]
+ ordering = ["game"]
diff --git a/game/templates/game/include/group_members.html b/game/templates/game/include/group_members.html
index 3b668e5..daf3059 100644
--- a/game/templates/game/include/group_members.html
+++ b/game/templates/game/include/group_members.html
@@ -12,7 +12,7 @@
-
+
|
diff --git a/game/templates/game/musikgame_answer.html b/game/templates/game/musikgame_answer.html
new file mode 100644
index 0000000..932d55e
--- /dev/null
+++ b/game/templates/game/musikgame_answer.html
@@ -0,0 +1,26 @@
+{% extends "base.html" %}
+{% block content %}
+ Mes réponses
+
+{% endblock content %}
diff --git a/game/templates/game/musikgame_detail.html b/game/templates/game/musikgame_detail.html
index 444c7f1..77f424c 100644
--- a/game/templates/game/musikgame_detail.html
+++ b/game/templates/game/musikgame_detail.html
@@ -10,6 +10,9 @@
href="{% yt_playlist musikgame %}"
role="button"
{% if musikgame.playlist_loading %}aria-busy="true"{% endif %}> Playlist
+ Répondre
{% endif %}
diff --git a/game/urls.py b/game/urls.py
index 6ec4cfa..15b8d3e 100644
--- a/game/urls.py
+++ b/game/urls.py
@@ -63,4 +63,9 @@ urlpatterns = [
views.GroupClearBlacklistView.as_view(),
name="group_clear_blacklist",
),
+ path(
+ "group/game//answer/",
+ views.GameAnswerView.as_view(),
+ name="game_answer",
+ ),
]
diff --git a/game/views.py b/game/views.py
index 3716424..3ebb49b 100644
--- a/game/views.py
+++ b/game/views.py
@@ -421,3 +421,34 @@ class GroupClearBlacklistView(MemberFilterMixin, SingleObjectMixin, View):
group.musicvideo_set.filter(blacklisted=True).update(blacklisted=False)
messages.add_message(request, messages.SUCCESS, "La blacklist a été effacée.")
return redirect(group)
+
+
+class GameAnswerView(LoginRequiredMixin, DetailView):
+ model = models.MusikGame
+ template_name = "game/musikgame_answer.html"
+
+ def get_queryset(self):
+ return super().get_queryset().filter(players=self.request.user)
+
+ def get_context_data(self, **kwargs):
+ return super().get_context_data(**kwargs) | {
+ "form": forms.AnswerForm(game=self.object, user=self.request.user)
+ }
+
+ def post(self, request, pk):
+ game = self.get_object()
+ for music in game.musicgameorder_set.all():
+ answer = request.POST.get(f"answer-{music.order}")
+ if answer:
+ models.MusicGameAnswer.objects.update_or_create(
+ game=music,
+ player=request.user,
+ defaults={"answer": game.players.get(pk=answer)},
+ )
+ else:
+ models.MusicGameAnswer.objects.update_or_create(
+ game=music,
+ player=request.user,
+ defaults={"answer": None},
+ )
+ return redirect("game_answer", pk)