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,
|
||||
QUESTION_TYPES,
|
||||
TALLY_FUNCTIONS,
|
||||
VALIDATE_FUNCTIONS,
|
||||
)
|
||||
from .utils import CastFunctions, TallyFunctions, choices_length
|
||||
from .utils import CastFunctions, TallyFunctions, ValidateFunctions, choices_length
|
||||
|
||||
# #############################################################################
|
||||
# Models regarding an election
|
||||
|
@ -77,6 +78,10 @@ class Question(models.Model):
|
|||
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):
|
||||
cast_function = getattr(CastFunctions, CAST_FUNCTIONS[self.type])
|
||||
cast_function(user, vote_form)
|
||||
|
|
|
@ -20,6 +20,7 @@ CONNECTION_METHODS = {
|
|||
|
||||
QUESTION_TYPES = [
|
||||
("assentiment", _("Assentiment")),
|
||||
("uninominal", _("Uninominal")),
|
||||
]
|
||||
|
||||
VOTE_RULES = {
|
||||
|
@ -27,13 +28,24 @@ VOTE_RULES = {
|
|||
"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 é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 = {
|
||||
"assentiment": "cast_select",
|
||||
"uninominal": "cast_select",
|
||||
}
|
||||
|
||||
TALLY_FUNCTIONS = {
|
||||
"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):
|
||||
"""On enregistre un vote classique"""
|
||||
vote_form.full_clean()
|
||||
selected, n_selected = [], []
|
||||
for v in vote_form:
|
||||
if v.cleaned_data["selected"]:
|
||||
|
@ -64,6 +63,33 @@ class TallyFunctions:
|
|||
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
|
||||
# #############################################################################
|
||||
|
|
|
@ -410,10 +410,12 @@ class VoteView(OpenElectionOnlyMixin, DetailView):
|
|||
self.object = self.get_object()
|
||||
vote_form = OptionFormSet(self.request.POST, instance=self.object)
|
||||
|
||||
# On enregistre le vote
|
||||
self.object.cast_ballot(self.request.user, vote_form)
|
||||
self.object.voters.add(self.request.user)
|
||||
if self.object.is_form_valid(vote_form):
|
||||
# On enregistre le vote
|
||||
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())
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
else:
|
||||
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 }}
|
||||
{% for form in formset %}
|
||||
{% include 'forms/form.html' %}
|
||||
|
|
Loading…
Reference in a new issue