from django.shortcuts import render, get_object_or_404, redirect from django.views.generic import ListView, CreateView, DetailView from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin from django.urls import reverse_lazy, reverse from django.db import transaction from .models import Poll, Choice from .forms import PollForm, ChoiceFormSet from clubs.models import Team from accounts.models import CustomUser class PollListView(LoginRequiredMixin, ListView): model = Poll template_name = 'polls/poll_list.html' context_object_name = 'polls' def get_queryset(self): user = self.request.user user_teams = set() if user.team: user_teams.add(user.team) # Add teams where the user is a coach or assistant user_teams.update(user.coached_teams.all()) user_teams.update(user.assisted_teams.all()) # Add teams of children for parents if hasattr(user, 'children'): for child in user.children.all(): if child.team: user_teams.add(child.team) return Poll.objects.filter(team__in=user_teams).order_by('-created_at') class PollCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView): model = Poll form_class = PollForm template_name = 'polls/poll_form.html' def test_func(self): # Only head coaches can create polls return self.request.user.coached_teams.exists() def get_context_data(self, **kwargs): data = super().get_context_data(**kwargs) if self.request.POST: data['choice_formset'] = ChoiceFormSet(self.request.POST) else: data['choice_formset'] = ChoiceFormSet() # Filter the team queryset for the form to only show teams the user coaches data['form'].fields['team'].queryset = self.request.user.coached_teams.all() return data def form_valid(self, form): context = self.get_context_data() choice_formset = context['choice_formset'] # Set the creator before saving the poll form.instance.creator = self.request.user if choice_formset.is_valid(): self.object = form.save() with transaction.atomic(): for choice_form in choice_formset: if choice_form.cleaned_data.get('choice_text'): Choice.objects.create( poll=self.object, choice_text=choice_form.cleaned_data['choice_text'] ) return redirect(self.get_success_url()) else: return self.form_invalid(form) def get_success_url(self): return reverse('polls:poll_list') class PollDetailView(LoginRequiredMixin, UserPassesTestMixin, DetailView): model = Poll template_name = 'polls/poll_detail.html' def test_func(self): # Check if user is part of the team for which the poll is poll = self.get_object() user = self.request.user user_teams = set() if user.team: user_teams.add(user.team) user_teams.update(user.coached_teams.all()) user_teams.update(user.assisted_teams.all()) if hasattr(user, 'children'): for child in user.children.all(): if child.team: user_teams.add(child.team) return poll.team in user_teams def vote(request, poll_id): poll = get_object_or_404(Poll, pk=poll_id) user = request.user if request.method == 'POST': if poll.multiple_choice: selected_choice_ids = request.POST.getlist('choice') # First, remove user's previous votes for this poll for choice in poll.choices.all(): choice.votes.remove(user) # Then, add new votes for choice_id in selected_choice_ids: choice = get_object_or_404(Choice, pk=choice_id) choice.votes.add(user) else: selected_choice_id = request.POST.get('choice') if selected_choice_id: # Remove user's vote from all choices in this poll first for choice in poll.choices.all(): choice.votes.remove(user) # Add the new vote choice = get_object_or_404(Choice, pk=selected_choice_id) choice.votes.add(user) return redirect('polls:poll_results', pk=poll.id) class PollResultsView(LoginRequiredMixin, DetailView): model = Poll template_name = 'polls/poll_results.html' context_object_name = 'poll'