kadenios/elections/views.py
2020-12-19 20:59:20 +01:00

174 lines
5.9 KiB
Python

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 import timezone
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from django.views.generic import CreateView, DetailView, RedirectView, UpdateView
from django.views.generic.detail import SingleObjectMixin
from .forms import OptionFormSet
from .models import Election, Option, Question
# TODO: access control *everywhere*
class ElectionCreateView(SuccessMessageMixin, CreateView):
model = Election
fields = ["name", "description", "start_date", "end_date"]
template_name = "elections/election_create.html"
success_message = _("Élection crée avec succès !")
def get_success_url(self):
return reverse("election.admin", args=[self.object.pk])
def form_valid(self, form):
# We need to add the short name and the creator od the election
form.instance.short_name = slugify(
str(form.instance.start_date.year) + "_" + form.instance.name
)[:50]
# TODO: Change this if we modify the user model
form.instance.created_by = self.request.user
return super().form_valid(form)
# TODO : only the creator can edit the election and view the admin panel
class ElectionAdminView(DetailView):
model = Election
template_name = "elections/election_admin.html"
def get_context_data(self, **kwargs):
kwargs.update({"current_time": timezone.now()})
return super().get_context_data(**kwargs)
def get_queryset(self):
return super().get_queryset().prefetch_related("questions__options")
class ElectionUpdateView(SuccessMessageMixin, UpdateView):
model = Election
fields = ["name", "description", "start_date", "end_date"]
success_message = _("Élection modifiée avec succès !")
template_name = "elections/election_update.html"
def get_success_url(self):
return reverse("election.admin", args=[self.object.pk])
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 ElectionTallyView(SuccessMessageMixin, SingleObjectMixin, RedirectView):
model = Election
pattern_name = "election.admin"
def get_queryset(self):
return super().get_queryset().prefetch_related("questions__options")
def get(self, request, *args, **kwargs):
election = self.get_object()
options, questions = [], []
for q in election.questions.all():
max_votes = 0
for o in q.options.all():
o.nb_votes = o.voters.count()
max_votes = max(max_votes, o.nb_votes)
options.append(o)
q.max_votes = max_votes
questions.append(q)
Option.objects.bulk_update(options, ["nb_votes"])
Question.objects.bulk_update(questions, ["max_votes"])
election.tallied = True
election.save()
messages.success(request, _("Élection dépouillée avec succès !"))
return super().get(request, *args, **kwargs)
class ElectionChangePublicationView(
SuccessMessageMixin, SingleObjectMixin, RedirectView
):
model = Election
pattern_name = "election.admin"
def get(self, request, *args, **kwargs):
election = self.get_object()
election.results_public = not election.results_public
election.save()
messages.success(
request,
_("Élection publiée avec succès !")
if election.results_public
else _("Élection dépubliée avec succès !"),
)
return super().get(request, *args, **kwargs)
class ElectionArchiveView(SuccessMessageMixin, SingleObjectMixin, RedirectView):
model = Election
pattern_name = "election.admin"
def get(self, request, *args, **kwargs):
election = self.get_object()
election.archived = True
election.save()
messages.success(request, _("Élection archivée avec succès !"))
return super().get(request, *args, **kwargs)
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}"
)