Add game answer functionality with form and view for user responses

This commit is contained in:
Edgar P. Burkhart 2025-06-15 12:40:55 +02:00
parent 6dbb1a54e0
commit d03d3b48d4
Signed by: edpibu
GPG key ID: 9833D3C5A25BD227
9 changed files with 97 additions and 12 deletions

View file

@ -130,3 +130,7 @@ td.c, th.c {
margin: 0;
}
}
table select {
margin-bottom: 0;
}

View file

@ -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 "",
)

View file

@ -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"
)
],
},

View file

@ -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"]

View file

@ -12,7 +12,7 @@
<i class="ri-vip-crown-fill"></i>
</th>
<th>
<i class="ri-mv-line"></i>
<i class="ri-mv-fill"></i>
</th>
</tr>
</thead>

View file

@ -0,0 +1,26 @@
{% extends "base.html" %}
{% block content %}
<h2>Mes réponses</h2>
<form method="post">
{% csrf_token %}
<table>
<thead>
<tr>
<th>
<i class="ri-mv-fill" alt="Musique"></i>
</th>
<th>Réponse</th>
</tr>
</thead>
<tbody>
{% for field in form %}
<tr>
<td>{{ field.label }}</td>
<td>{{ field }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<button type="submit">Valider mes réponses</button>
</form>
{% endblock content %}

View file

@ -10,6 +10,9 @@
href="{% yt_playlist musikgame %}"
role="button"
{% if musikgame.playlist_loading %}aria-busy="true"{% endif %}><i class="ri-youtube-fill"></i> Playlist</a>
<a target="_blank"
href="{% url "game_answer" musikgame.pk %}"
role="button"><i class="ri-play-list-2-fill"></i> Répondre</a>
</p>
{% endif %}
<h2>

View file

@ -63,4 +63,9 @@ urlpatterns = [
views.GroupClearBlacklistView.as_view(),
name="group_clear_blacklist",
),
path(
"group/game/<int:pk>/answer/",
views.GameAnswerView.as_view(),
name="game_answer",
),
]

View file

@ -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)