kadenios/elections/views.py

191 lines
6.3 KiB
Python
Raw Normal View History

from django.contrib import messages
2020-11-20 17:46:53 +01:00
from django.contrib.messages.views import SuccessMessageMixin
from django.db.models import Count, Prefetch
2020-12-18 00:19:18 +01:00
from django.http import HttpResponseRedirect
from django.urls import reverse
2020-12-19 16:57:28 +01:00
from django.utils import timezone
2020-12-19 20:58:38 +01:00
from django.utils.text import slugify
2020-12-18 00:19:18 +01:00
from django.utils.translation import gettext_lazy as _
2020-12-19 16:57:28 +01:00
from django.views.generic import CreateView, DetailView, RedirectView, UpdateView
from django.views.generic.detail import SingleObjectMixin
2020-11-20 17:46:53 +01:00
2020-12-19 22:22:23 +01:00
from .forms import ElectionCreateForm, OptionFormSet
2020-12-18 00:19:18 +01:00
from .models import Election, Option, Question
2020-11-20 17:46:53 +01:00
# TODO: access control *everywhere*
class ElectionCreateView(SuccessMessageMixin, CreateView):
model = Election
2020-12-19 22:22:23 +01:00
form_class = ElectionCreateForm
2020-11-20 19:31:22 +01:00
template_name = "elections/election_create.html"
2020-12-19 22:22:23 +01:00
success_message = _("Élection créée avec succès !")
2020-11-20 17:46:53 +01:00
2020-12-19 20:58:38 +01:00
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(
2020-12-19 22:22:23 +01:00
form.instance.start_date.strftime("%Y-%m-%d") + "_" + form.instance.name
2020-12-19 20:58:38 +01:00
)[:50]
# TODO: Change this if we modify the user model
form.instance.created_by = self.request.user
return super().form_valid(form)
2020-11-20 17:46:53 +01:00
2020-12-19 15:04:04 +01:00
# TODO : only the creator can edit the election and view the admin panel
class ElectionAdminView(DetailView):
model = Election
template_name = "elections/election_admin.html"
2020-12-19 16:57:28 +01:00
def get_context_data(self, **kwargs):
kwargs.update({"current_time": timezone.now()})
return super().get_context_data(**kwargs)
2020-12-19 15:04:04 +01:00
def get_queryset(self):
return super().get_queryset().prefetch_related("questions__options")
2020-11-20 17:46:53 +01:00
class ElectionUpdateView(SuccessMessageMixin, UpdateView):
model = Election
2020-12-19 15:04:04 +01:00
fields = ["name", "description", "start_date", "end_date"]
2020-11-20 17:46:53 +01:00
success_message = _("Élection modifiée avec succès !")
2020-12-19 16:57:28 +01:00
template_name = "elections/election_update.html"
def get_success_url(self):
return reverse("election.admin", args=[self.object.pk])
2020-11-20 17:46:53 +01:00
def get_queryset(self):
2020-12-19 22:22:23 +01:00
# On ne peut plus modifier une élection qui a déjà commencé
return super().get_queryset().filter(start_date__gt=timezone.now())
2020-11-20 17:46:53 +01:00
2020-12-19 16:57:28 +01:00
class ElectionTallyView(SuccessMessageMixin, SingleObjectMixin, RedirectView):
model = Election
pattern_name = "election.admin"
def get_queryset(self):
2020-12-19 22:22:23 +01:00
return (
super()
.get_queryset()
.filter(end_date__lt=timezone.now())
.prefetch_related("questions__options")
)
2020-12-19 16:57:28 +01:00
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 !"))
2020-12-19 16:57:28 +01:00
return super().get(request, *args, **kwargs)
class ElectionChangePublicationView(
SuccessMessageMixin, SingleObjectMixin, RedirectView
):
2020-12-19 16:57:28 +01:00
model = Election
pattern_name = "election.admin"
2020-12-19 16:57:28 +01:00
2020-12-19 22:22:23 +01:00
def get_queryset(self):
return super().get_queryset().filter(end_date__lt=timezone.now())
2020-12-19 16:57:28 +01:00
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 !"),
)
2020-12-19 16:57:28 +01:00
return super().get(request, *args, **kwargs)
class ElectionArchiveView(SuccessMessageMixin, SingleObjectMixin, RedirectView):
model = Election
pattern_name = "election.admin"
2020-12-19 16:57:28 +01:00
2020-12-19 22:22:23 +01:00
def get_queryset(self):
return super().get_queryset().filter(end_date__lt=timezone.now())
2020-12-19 16:57:28 +01:00
def get(self, request, *args, **kwargs):
election = self.get_object()
election.archived = True
election.save()
messages.success(request, _("Élection archivée avec succès !"))
2020-12-19 16:57:28 +01:00
return super().get(request, *args, **kwargs)
2020-11-20 17:46:53 +01:00
class ElectionView(DetailView):
model = Election
2020-12-18 00:19:18 +01:00
template_name = "elections/election.html"
2020-11-20 17:46:53 +01:00
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
2020-12-18 00:19:18 +01:00
if self.object.tallied:
2020-11-20 17:46:53 +01:00
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):
2020-12-18 00:19:18 +01:00
return super().get_queryset().filter(archived=False)
class VoteView(SuccessMessageMixin, DetailView):
2020-12-18 00:19:18 +01:00
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()
2020-12-19 22:22:23 +01:00
.filter(
election__tallied=False,
election__archived=False,
election__start_date__lt=timezone.now(),
election__end_date__gt=timezone.now(),
)
2020-12-18 00:19:18 +01:00
.select_related("election")
)
def get(self, request, *args, **kwargs):
self.object = self.get_object()
vote_form = OptionFormSet(instance=self.object)
2020-12-18 17:38:44 +01:00
return self.render_to_response(self.get_context_data(formset=vote_form))
2020-12-18 00:19:18 +01:00
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é !"))
2020-12-18 00:19:18 +01:00
return HttpResponseRedirect(
reverse("election.view", args=[self.object.election.pk])
+ f"#q_{self.object.pk}"
)