from django.contrib import messages from django.contrib.messages.views import SuccessMessageMixin from django.db.models import Count, Prefetch from django.http import HttpResponseRedirect from django.urls import reverse from django.utils.translation import gettext_lazy as _ from django.views.generic import CreateView, DetailView, UpdateView from .forms import ElectionCreateForm, OptionFormSet from .models import Election, Option, Question # TODO: access control *everywhere* class ElectionCreateView(SuccessMessageMixin, CreateView): model = Election form_class = ElectionCreateForm template_name = "elections/election_create.html" success_message = _("Élection crée avec succès !") class ElectionUpdateView(SuccessMessageMixin, UpdateView): model = Election fields = ["name", "description", "start_time", "end_time"] success_message = _("Élection modifiée avec succès !") def get_queryset(self): # On ne peut plus modifier une élection déjà comptée return super().get_queryset().filter(tallied=False, archived=False) class ElectionView(DetailView): model = Election template_name = "elections/election.html" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) if self.object.tallied: options_qs = Option.objects.annotate(nb_votes=Count("voters")) questions = self.election.question.prefetch_related( Prefetch("options", queryset=options_qs) ) context["questions"] = questions return context def get_queryset(self): return super().get_queryset().filter(archived=False) class VoteView(SuccessMessageMixin, DetailView): model = Question template_name = "elections/vote.html" def get_queryset(self): # On ne peut voter que si l'élection n'a pas été comptée return ( super() .get_queryset() .filter(election__tallied=False, election__archived=False) .select_related("election") ) def get(self, request, *args, **kwargs): self.object = self.get_object() vote_form = OptionFormSet(instance=self.object) return self.render_to_response(self.get_context_data(formset=vote_form)) def post(self, request, *args, **kwargs): self.object = self.get_object() vote_form = OptionFormSet(self.request.POST, instance=self.object) # We record the cast votes for v in vote_form: v.record_vote(self.request.user) messages.success(self.request, _("Votre vote a bien été enregistré !")) return HttpResponseRedirect( reverse("election.view", args=[self.object.election.pk]) + f"#q_{self.object.pk}" )