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

+
+ {% csrf_token %} + + + + + + + + + {% for field in form %} + + + + + {% endfor %} + +
+ + Réponse
{{ field.label }}{{ field }}
+ +
+{% 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)