musik/game/views.py

139 lines
4.2 KiB
Python

import random
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import Count, Q
from django.http import JsonResponse
from django.shortcuts import redirect
from django.views import View
from django.views.generic.detail import DetailView, SingleObjectMixin
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from . import forms, models, utils
class OwnerFilterMixin(LoginRequiredMixin):
def get_queryset(self):
return super().get_queryset().filter(owner=self.request.user)
class MemberFilterMixin(LoginRequiredMixin):
def get_queryset(self):
return (
super()
.get_queryset()
.filter(Q(members=self.request.user) | Q(owner=self.request.user))
)
class GroupMixin:
model = models.Group
fields = ["name"]
class GroupCreateView(LoginRequiredMixin, GroupMixin, CreateView):
def form_valid(self, form):
form.instance.owner = self.request.user
return super().form_valid(form)
class GroupUpdateView(OwnerFilterMixin, GroupMixin, UpdateView):
pass
class GroupDeleteView(OwnerFilterMixin, GroupMixin, DeleteView):
success_url = "/"
class GroupDetailView(MemberFilterMixin, GroupMixin, DetailView):
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
data["musics"] = data["group"].musicvideo_set.filter(owner=self.request.user)
data["owner_count"] = (
data["group"].musicvideo_set.filter(owner=data["group"].owner).count()
)
data["members"] = data["group"].members.annotate(
count=Count("musicvideo", filter=Q(group=data["group"]))
)
return data
class GroupAddMembersView(OwnerFilterMixin, GroupMixin, UpdateView):
fields = None
form_class = forms.GroupAddMembersForm
class GroupAddMusicView(MemberFilterMixin, SingleObjectMixin, View):
model = models.Group
def post(self, request, pk):
group = self.get_object()
yt_id = request.POST.get("yt_id")
if not yt_id:
return JsonResponse({"error": "You must provide a YouTube ID."}, status=400)
yt_id = utils.parse_musik(yt_id)
title = utils.get_yt_title(yt_id)
if not title:
return JsonResponse({"error": "Invalid YouTube ID."}, status=400)
group.musicvideo_set.create(yt_id=yt_id, title=title, owner=request.user)
group.save()
return redirect(group)
class GroupRemoveMusicView(OwnerFilterMixin, SingleObjectMixin, View):
model = models.MusicVideo
def get(self, request, pk):
music = self.get_object()
group = music.group
music.delete()
return redirect(group)
class GameCreateView(LoginRequiredMixin, CreateView):
model = models.MusikGame
form_class = forms.MusikGameForm
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs["group"] = self.kwargs["pk"]
return kwargs
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
data["group"] = models.Group.objects.filter(owner=self.request.user).get(
pk=self.kwargs["pk"]
)
return data
def form_valid(self, form):
group = models.Group.objects.get(pk=self.kwargs["pk"])
form.instance.group = group
res = super().form_valid(form)
players = []
musics = []
for player in form.instance.players.all():
players += 2 * [player]
musics += random.sample(
list(
player.musicvideo_set.filter(group=group, blacklisted=False).all()
),
form.instance.n,
)
pm_list = list(zip(players, musics))
random.shuffle(pm_list)
for (player, music), order in zip(pm_list, range(len(pm_list))):
models.MusicGameOrder.objects.create(
game=form.instance, player=player, music_video=music, order=order
)
return res
class GameDetailView(LoginRequiredMixin, DetailView):
model = models.MusikGame
def get_queryset(self):
return super().get_queryset().filter(group__owner=self.request.user)