Add game answer functionality with form and view for user responses
This commit is contained in:
parent
6dbb1a54e0
commit
d03d3b48d4
9 changed files with 97 additions and 12 deletions
|
@ -130,3 +130,7 @@ td.c, th.c {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table select {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
|
@ -39,3 +39,22 @@ class MusikGameForm(forms.ModelForm):
|
||||||
kwargs["initial"].setdefault("players", players)
|
kwargs["initial"].setdefault("players", players)
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.fields["players"].queryset = players
|
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 "",
|
||||||
|
)
|
||||||
|
|
|
@ -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
|
import django.db.models.deletion
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -24,7 +24,6 @@ class Migration(migrations.Migration):
|
||||||
verbose_name="ID",
|
verbose_name="ID",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("order", models.PositiveIntegerField()),
|
|
||||||
(
|
(
|
||||||
"answer",
|
"answer",
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
|
@ -37,7 +36,8 @@ class Migration(migrations.Migration):
|
||||||
(
|
(
|
||||||
"game",
|
"game",
|
||||||
models.ForeignKey(
|
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={
|
options={
|
||||||
"ordering": ["order"],
|
"ordering": ["game"],
|
||||||
"constraints": [
|
"constraints": [
|
||||||
models.UniqueConstraint(
|
models.UniqueConstraint(
|
||||||
fields=("game", "player", "order"), name="unique_answer"
|
fields=("game", "player"), name="unique_answer"
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -114,17 +114,14 @@ class MusicGameOrder(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class MusicGameAnswer(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)
|
player = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
order = models.PositiveIntegerField()
|
|
||||||
answer = models.ForeignKey(
|
answer = models.ForeignKey(
|
||||||
User, on_delete=models.SET_NULL, null=True, related_name="+"
|
User, on_delete=models.SET_NULL, null=True, related_name="+"
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
constraints = [
|
constraints = [
|
||||||
models.UniqueConstraint(
|
models.UniqueConstraint(fields=("game", "player"), name="unique_answer"),
|
||||||
fields=("game", "player", "order"), name="unique_answer"
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
ordering = ["order"]
|
ordering = ["game"]
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<i class="ri-vip-crown-fill"></i>
|
<i class="ri-vip-crown-fill"></i>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<i class="ri-mv-line"></i>
|
<i class="ri-mv-fill"></i>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
26
game/templates/game/musikgame_answer.html
Normal file
26
game/templates/game/musikgame_answer.html
Normal 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 %}
|
|
@ -10,6 +10,9 @@
|
||||||
href="{% yt_playlist musikgame %}"
|
href="{% yt_playlist musikgame %}"
|
||||||
role="button"
|
role="button"
|
||||||
{% if musikgame.playlist_loading %}aria-busy="true"{% endif %}><i class="ri-youtube-fill"></i> Playlist</a>
|
{% 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>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<h2>
|
<h2>
|
||||||
|
|
|
@ -63,4 +63,9 @@ urlpatterns = [
|
||||||
views.GroupClearBlacklistView.as_view(),
|
views.GroupClearBlacklistView.as_view(),
|
||||||
name="group_clear_blacklist",
|
name="group_clear_blacklist",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"group/game/<int:pk>/answer/",
|
||||||
|
views.GameAnswerView.as_view(),
|
||||||
|
name="game_answer",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -421,3 +421,34 @@ class GroupClearBlacklistView(MemberFilterMixin, SingleObjectMixin, View):
|
||||||
group.musicvideo_set.filter(blacklisted=True).update(blacklisted=False)
|
group.musicvideo_set.filter(blacklisted=True).update(blacklisted=False)
|
||||||
messages.add_message(request, messages.SUCCESS, "La blacklist a été effacée.")
|
messages.add_message(request, messages.SUCCESS, "La blacklist a été effacée.")
|
||||||
return redirect(group)
|
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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue