On rajoute une validation pour les formsets selon le type de question, et on rajoute le vote uninominal
This commit is contained in:
parent
4a99c3d6f5
commit
d2161a70d7
6 changed files with 87 additions and 9 deletions
23
elections/migrations/0012_auto_20210319_1613.py
Normal file
23
elections/migrations/0012_auto_20210319_1613.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 2.2.19 on 2021-03-19 15:13
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("elections", "0011_question_type"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="question",
|
||||||
|
name="type",
|
||||||
|
field=models.CharField(
|
||||||
|
choices=[("assentiment", "Assentiment"), ("uninominal", "Uninominal")],
|
||||||
|
default="assentiment",
|
||||||
|
max_length=11,
|
||||||
|
verbose_name="type de question",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -8,8 +8,9 @@ from .staticdefs import (
|
||||||
CONNECTION_METHODS,
|
CONNECTION_METHODS,
|
||||||
QUESTION_TYPES,
|
QUESTION_TYPES,
|
||||||
TALLY_FUNCTIONS,
|
TALLY_FUNCTIONS,
|
||||||
|
VALIDATE_FUNCTIONS,
|
||||||
)
|
)
|
||||||
from .utils import CastFunctions, TallyFunctions, choices_length
|
from .utils import CastFunctions, TallyFunctions, ValidateFunctions, choices_length
|
||||||
|
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
# Models regarding an election
|
# Models regarding an election
|
||||||
|
@ -77,6 +78,10 @@ class Question(models.Model):
|
||||||
blank=True,
|
blank=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def is_form_valid(self, vote_form):
|
||||||
|
validate_function = getattr(ValidateFunctions, VALIDATE_FUNCTIONS[self.type])
|
||||||
|
return vote_form.is_valid() and validate_function(vote_form)
|
||||||
|
|
||||||
def cast_ballot(self, user, vote_form):
|
def cast_ballot(self, user, vote_form):
|
||||||
cast_function = getattr(CastFunctions, CAST_FUNCTIONS[self.type])
|
cast_function = getattr(CastFunctions, CAST_FUNCTIONS[self.type])
|
||||||
cast_function(user, vote_form)
|
cast_function(user, vote_form)
|
||||||
|
|
|
@ -20,6 +20,7 @@ CONNECTION_METHODS = {
|
||||||
|
|
||||||
QUESTION_TYPES = [
|
QUESTION_TYPES = [
|
||||||
("assentiment", _("Assentiment")),
|
("assentiment", _("Assentiment")),
|
||||||
|
("uninominal", _("Uninominal")),
|
||||||
]
|
]
|
||||||
|
|
||||||
VOTE_RULES = {
|
VOTE_RULES = {
|
||||||
|
@ -27,13 +28,24 @@ VOTE_RULES = {
|
||||||
"Le mode de scrutin pour cette question est un vote par assentiment. "
|
"Le mode de scrutin pour cette question est un vote par assentiment. "
|
||||||
"Vous pouvez donc sélectionner autant d'options que vous souhaitez. "
|
"Vous pouvez donc sélectionner autant d'options que vous souhaitez. "
|
||||||
"Vous pouvez également ne sélectionner aucune option."
|
"Vous pouvez également ne sélectionner aucune option."
|
||||||
)
|
),
|
||||||
|
"uninominal": _(
|
||||||
|
"Le mode de scrutin pour cette question est un vote uninominal. "
|
||||||
|
"Vous ne pouvez donc sélectionner qu'une seule option."
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
CAST_FUNCTIONS = {
|
CAST_FUNCTIONS = {
|
||||||
"assentiment": "cast_select",
|
"assentiment": "cast_select",
|
||||||
|
"uninominal": "cast_select",
|
||||||
}
|
}
|
||||||
|
|
||||||
TALLY_FUNCTIONS = {
|
TALLY_FUNCTIONS = {
|
||||||
"assentiment": "tally_select",
|
"assentiment": "tally_select",
|
||||||
|
"uninominal": "tally_select",
|
||||||
|
}
|
||||||
|
|
||||||
|
VALIDATE_FUNCTIONS = {
|
||||||
|
"assentiment": "always_true",
|
||||||
|
"uninominal": "unique_selected",
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ class CastFunctions:
|
||||||
|
|
||||||
def cast_select(user, vote_form):
|
def cast_select(user, vote_form):
|
||||||
"""On enregistre un vote classique"""
|
"""On enregistre un vote classique"""
|
||||||
vote_form.full_clean()
|
|
||||||
selected, n_selected = [], []
|
selected, n_selected = [], []
|
||||||
for v in vote_form:
|
for v in vote_form:
|
||||||
if v.cleaned_data["selected"]:
|
if v.cleaned_data["selected"]:
|
||||||
|
@ -64,6 +63,33 @@ class TallyFunctions:
|
||||||
Option.objects.bulk_update(options, ["nb_votes"])
|
Option.objects.bulk_update(options, ["nb_votes"])
|
||||||
|
|
||||||
|
|
||||||
|
class ValidateFunctions:
|
||||||
|
"""Classe pour valider les formsets selon le type de question"""
|
||||||
|
|
||||||
|
def always_true(vote_form):
|
||||||
|
"""Retourne True pour les votes sans validation particulière"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def unique_selected(vote_form):
|
||||||
|
"""Vérifie qu'une seule option est choisie"""
|
||||||
|
print("toto")
|
||||||
|
nb_selected = 0
|
||||||
|
for v in vote_form:
|
||||||
|
nb_selected += v.cleaned_data["selected"]
|
||||||
|
|
||||||
|
if nb_selected == 0:
|
||||||
|
vote_form._non_form_errors.append(
|
||||||
|
ValidationError(_("Vous devez sélectionnner une option."))
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
elif nb_selected > 1:
|
||||||
|
vote_form._non_form_errors.append(
|
||||||
|
ValidationError(_("Vous ne pouvez pas sélectionner plus d'une option."))
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
# Fonctions pour importer une liste de votant·e·s
|
# Fonctions pour importer une liste de votant·e·s
|
||||||
# #############################################################################
|
# #############################################################################
|
||||||
|
|
|
@ -410,10 +410,12 @@ class VoteView(OpenElectionOnlyMixin, DetailView):
|
||||||
self.object = self.get_object()
|
self.object = self.get_object()
|
||||||
vote_form = OptionFormSet(self.request.POST, instance=self.object)
|
vote_form = OptionFormSet(self.request.POST, instance=self.object)
|
||||||
|
|
||||||
# On enregistre le vote
|
if self.object.is_form_valid(vote_form):
|
||||||
self.object.cast_ballot(self.request.user, vote_form)
|
# On enregistre le vote
|
||||||
self.object.voters.add(self.request.user)
|
self.object.cast_ballot(self.request.user, vote_form)
|
||||||
|
self.object.voters.add(self.request.user)
|
||||||
|
messages.success(self.request, _("Votre choix a bien été enregistré !"))
|
||||||
|
|
||||||
messages.success(self.request, _("Votre choix a bien été enregistré !"))
|
return HttpResponseRedirect(self.get_success_url())
|
||||||
|
else:
|
||||||
return HttpResponseRedirect(self.get_success_url())
|
return self.render_to_response(self.get_context_data(formset=vote_form))
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
{% if formset.non_form_errors %}
|
||||||
|
<div class="message is-danger">
|
||||||
|
<p class="message-body">
|
||||||
|
{% for error in formset.non_form_errors %}
|
||||||
|
{{ error }}
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{{ formset.management_form }}
|
{{ formset.management_form }}
|
||||||
{% for form in formset %}
|
{% for form in formset %}
|
||||||
{% include 'forms/form.html' %}
|
{% include 'forms/form.html' %}
|
||||||
|
|
Loading…
Reference in a new issue