Début du vote
This commit is contained in:
parent
492e0731a7
commit
3d8a225ed1
5 changed files with 101 additions and 8 deletions
31
elections/forms.py
Normal file
31
elections/forms.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
from django import forms
|
||||||
|
from django.forms.models import inlineformset_factory
|
||||||
|
|
||||||
|
from .models import Option, Question
|
||||||
|
|
||||||
|
|
||||||
|
class VoteForm(forms.ModelForm):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
# We set the option's text as the label for the checkbox
|
||||||
|
instance = kwargs.get("instance", None)
|
||||||
|
if instance is not None:
|
||||||
|
self.fields["selected"].label = instance.text
|
||||||
|
|
||||||
|
selected = forms.BooleanField(required=False)
|
||||||
|
|
||||||
|
def record_vote(self, user):
|
||||||
|
self.full_clean()
|
||||||
|
if self.cleaned_data["selected"]:
|
||||||
|
self.instance.voters.add(user)
|
||||||
|
else:
|
||||||
|
self.instance.voters.remove(user)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Option
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
|
||||||
|
OptionFormSet = inlineformset_factory(
|
||||||
|
Question, Option, extra=0, form=VoteForm, can_delete=False
|
||||||
|
)
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<p class="control">
|
<p class="control">
|
||||||
<input class="button is-fullwidth" type="submit" value="Enregistrer">
|
<input class="button is-fullwidth" type="submit" value={% trans "Enregistrer" %}>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
23
elections/templates/elections/vote.html
Normal file
23
elections/templates/elections/vote.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{% extends "elections/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h1 class="title">{% trans "Vote pour la question :" %} {{ question }}</h1>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<form action="" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{{ vote_form }}
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<p class="control">
|
||||||
|
<input class="button is-fullwidth" type="submit" value="Enregistrer">
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -1,8 +1,10 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("create/", views.ElectionCreateView.as_view(), name="election.create"),
|
path("create/", views.ElectionCreateView.as_view(), name="election.create"),
|
||||||
path("update/<int:pk>", views.ElectionUpdateView.as_view(), name="election.update"),
|
path("update/<int:pk>", views.ElectionUpdateView.as_view(), name="election.update"),
|
||||||
path("view/<int:pk>", views.ElectionView.as_view(), name="election.view"),
|
path("view/<int:pk>", views.ElectionView.as_view(), name="election.view"),
|
||||||
|
path("vote/<int:pk>", views.VoteView.as_view(), name="election.vote"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
from django.views.generic import CreateView, UpdateView, DetailView
|
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
from django.db.models import Count, Prefetch
|
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 .models import Election, Question, Option
|
from .forms import OptionFormSet
|
||||||
|
from .models import Election, Option, Question
|
||||||
|
|
||||||
# TODO: access control *everywhere*
|
# TODO: access control *everywhere*
|
||||||
|
|
||||||
|
@ -27,10 +30,11 @@ class ElectionUpdateView(SuccessMessageMixin, UpdateView):
|
||||||
|
|
||||||
class ElectionView(DetailView):
|
class ElectionView(DetailView):
|
||||||
model = Election
|
model = Election
|
||||||
|
template_name = "elections/election.html"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
if self.election.tallied:
|
if self.object.tallied:
|
||||||
options_qs = Option.objects.annotate(nb_votes=Count("voters"))
|
options_qs = Option.objects.annotate(nb_votes=Count("voters"))
|
||||||
questions = self.election.question.prefetch_related(
|
questions = self.election.question.prefetch_related(
|
||||||
Prefetch("options", queryset=options_qs)
|
Prefetch("options", queryset=options_qs)
|
||||||
|
@ -40,4 +44,37 @@ class ElectionView(DetailView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super().get_queryset().filter(archived=False).select_related("questions")
|
return super().get_queryset().filter(archived=False)
|
||||||
|
|
||||||
|
|
||||||
|
class VoteView(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(vote_form=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)
|
||||||
|
|
||||||
|
return HttpResponseRedirect(
|
||||||
|
reverse("election.view", args=[self.object.election.pk])
|
||||||
|
+ f"#q_{self.object.pk}"
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue