From be42a042a0f0ddf3c4e6ab3765cf5b7a62278417 Mon Sep 17 00:00:00 2001 From: imperosol Date: Fri, 14 Mar 2025 18:22:17 +0100 Subject: [PATCH] move forms to their own file --- election/forms.py | 164 ++++++++++++++++++++++++++++++++++++++++++++ election/views.py | 169 ++-------------------------------------------- 2 files changed, 171 insertions(+), 162 deletions(-) create mode 100644 election/forms.py diff --git a/election/forms.py b/election/forms.py new file mode 100644 index 00000000..5032e859 --- /dev/null +++ b/election/forms.py @@ -0,0 +1,164 @@ +from django import forms +from django.db import transaction +from django.db.models import QuerySet +from django.shortcuts import get_object_or_404 +from django.urls import reverse_lazy +from django.utils.translation import gettext_lazy as _ +from django.views.generic import FormView + +from core.auth.mixins import CanCreateMixin +from core.views.forms import SelectDateTime +from core.views.widgets.ajax_select import ( + AutoCompleteSelect, + AutoCompleteSelectMultipleGroup, + AutoCompleteSelectUser, +) +from core.views.widgets.markdown import MarkdownInput +from election.models import Candidature, Election, ElectionList, Role, Vote + + +class LimitedCheckboxField(forms.ModelMultipleChoiceField): + """A `ModelMultipleChoiceField`, with a max limit of selectable inputs.""" + + def __init__(self, queryset, max_choice, **kwargs): + self.max_choice = max_choice + super().__init__(queryset, **kwargs) + + def clean(self, value): + qs = super().clean(value) + self.validate(qs) + return qs + + def validate(self, qs): + if qs.count() > self.max_choice: + raise forms.ValidationError( + _("You have selected too much candidates."), code="invalid" + ) + + +class CandidateForm(forms.ModelForm): + """Form to candidate.""" + + class Meta: + model = Candidature + fields = ["user", "role", "program", "election_list"] + labels = { + "user": _("User to candidate"), + } + widgets = { + "program": MarkdownInput, + "user": AutoCompleteSelectUser, + "role": AutoCompleteSelect, + "election_list": AutoCompleteSelect, + } + + def __init__(self, *args, **kwargs): + election_id = kwargs.pop("election_id", None) + can_edit = kwargs.pop("can_edit", False) + super().__init__(*args, **kwargs) + if election_id: + self.fields["role"].queryset = Role.objects.filter( + election__id=election_id + ).all() + self.fields["election_list"].queryset = ElectionList.objects.filter( + election__id=election_id + ).all() + if not can_edit: + self.fields["user"].widget = forms.HiddenInput() + + +class VoteForm(forms.Form): + def __init__(self, election, user, *args, **kwargs): + super().__init__(*args, **kwargs) + if not election.has_voted(user): + for role in election.roles.all(): + cand = role.candidatures + if role.max_choice > 1: + self.fields[role.title] = LimitedCheckboxField( + cand, role.max_choice, required=False + ) + else: + self.fields[role.title] = forms.ModelChoiceField( + cand, + required=False, + widget=forms.RadioSelect(), + empty_label=_("Blank vote"), + ) + + +class RoleForm(forms.ModelForm): + """Form for creating a role.""" + + class Meta: + model = Role + fields = ["title", "election", "description", "max_choice"] + widgets = {"election": AutoCompleteSelect} + + def __init__(self, *args, **kwargs): + election_id = kwargs.pop("election_id", None) + super().__init__(*args, **kwargs) + if election_id: + self.fields["election"].queryset = Election.objects.filter( + id=election_id + ).all() + + def clean(self): + cleaned_data = super().clean() + title = cleaned_data.get("title") + election = cleaned_data.get("election") + if Role.objects.filter(title=title, election=election).exists(): + raise forms.ValidationError( + _("This role already exists for this election"), code="invalid" + ) + + +class ElectionListForm(forms.ModelForm): + class Meta: + model = ElectionList + fields = ("title", "election") + widgets = {"election": AutoCompleteSelect} + + def __init__(self, *args, **kwargs): + election_id = kwargs.pop("election_id", None) + super().__init__(*args, **kwargs) + if election_id: + self.fields["election"].queryset = Election.objects.filter( + id=election_id + ).all() + + +class ElectionForm(forms.ModelForm): + class Meta: + model = Election + fields = [ + "title", + "description", + "archived", + "start_candidature", + "end_candidature", + "start_date", + "end_date", + "edit_groups", + "view_groups", + "vote_groups", + "candidature_groups", + ] + widgets = { + "edit_groups": AutoCompleteSelectMultipleGroup, + "view_groups": AutoCompleteSelectMultipleGroup, + "vote_groups": AutoCompleteSelectMultipleGroup, + "candidature_groups": AutoCompleteSelectMultipleGroup, + } + + start_date = forms.DateTimeField( + label=_("Start date"), widget=SelectDateTime, required=True + ) + end_date = forms.DateTimeField( + label=_("End date"), widget=SelectDateTime, required=True + ) + start_candidature = forms.DateTimeField( + label=_("Start candidature"), widget=SelectDateTime, required=True + ) + end_candidature = forms.DateTimeField( + label=_("End candidature"), widget=SelectDateTime, required=True + ) diff --git a/election/views.py b/election/views.py index 25866422..ed0570e5 100644 --- a/election/views.py +++ b/election/views.py @@ -1,183 +1,28 @@ from typing import TYPE_CHECKING -from django import forms from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from django.core.exceptions import PermissionDenied from django.db import transaction -from django.db.models.query import QuerySet +from django.db.models import QuerySet from django.shortcuts import get_object_or_404, redirect from django.urls import reverse, reverse_lazy -from django.utils.translation import gettext_lazy as _ from django.views.generic import DetailView, ListView from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView from core.auth.mixins import CanCreateMixin, CanEditMixin, CanViewMixin -from core.views.forms import SelectDateTime -from core.views.widgets.ajax_select import ( - AutoCompleteSelect, - AutoCompleteSelectMultipleGroup, - AutoCompleteSelectUser, +from election.forms import ( + CandidateForm, + ElectionForm, + ElectionListForm, + RoleForm, + VoteForm, ) -from core.views.widgets.markdown import MarkdownInput from election.models import Candidature, Election, ElectionList, Role, Vote if TYPE_CHECKING: from core.models import User -# Custom form field - - -class LimitedCheckboxField(forms.ModelMultipleChoiceField): - """A `ModelMultipleChoiceField`, with a max limit of selectable inputs.""" - - def __init__(self, queryset, max_choice, **kwargs): - self.max_choice = max_choice - super().__init__(queryset, **kwargs) - - def clean(self, value): - qs = super().clean(value) - self.validate(qs) - return qs - - def validate(self, qs): - if qs.count() > self.max_choice: - raise forms.ValidationError( - _("You have selected too much candidates."), code="invalid" - ) - - -# Forms - - -class CandidateForm(forms.ModelForm): - """Form to candidate.""" - - class Meta: - model = Candidature - fields = ["user", "role", "program", "election_list"] - labels = { - "user": _("User to candidate"), - } - widgets = { - "program": MarkdownInput, - "user": AutoCompleteSelectUser, - "role": AutoCompleteSelect, - "election_list": AutoCompleteSelect, - } - - def __init__(self, *args, **kwargs): - election_id = kwargs.pop("election_id", None) - can_edit = kwargs.pop("can_edit", False) - super().__init__(*args, **kwargs) - if election_id: - self.fields["role"].queryset = Role.objects.filter( - election__id=election_id - ).all() - self.fields["election_list"].queryset = ElectionList.objects.filter( - election__id=election_id - ).all() - if not can_edit: - self.fields["user"].widget = forms.HiddenInput() - - -class VoteForm(forms.Form): - def __init__(self, election, user, *args, **kwargs): - super().__init__(*args, **kwargs) - if not election.has_voted(user): - for role in election.roles.all(): - cand = role.candidatures - if role.max_choice > 1: - self.fields[role.title] = LimitedCheckboxField( - cand, role.max_choice, required=False - ) - else: - self.fields[role.title] = forms.ModelChoiceField( - cand, - required=False, - widget=forms.RadioSelect(), - empty_label=_("Blank vote"), - ) - - -class RoleForm(forms.ModelForm): - """Form for creating a role.""" - - class Meta: - model = Role - fields = ["title", "election", "description", "max_choice"] - widgets = {"election": AutoCompleteSelect} - - def __init__(self, *args, **kwargs): - election_id = kwargs.pop("election_id", None) - super().__init__(*args, **kwargs) - if election_id: - self.fields["election"].queryset = Election.objects.filter( - id=election_id - ).all() - - def clean(self): - cleaned_data = super().clean() - title = cleaned_data.get("title") - election = cleaned_data.get("election") - if Role.objects.filter(title=title, election=election).exists(): - raise forms.ValidationError( - _("This role already exists for this election"), code="invalid" - ) - - -class ElectionListForm(forms.ModelForm): - class Meta: - model = ElectionList - fields = ("title", "election") - widgets = {"election": AutoCompleteSelect} - - def __init__(self, *args, **kwargs): - election_id = kwargs.pop("election_id", None) - super().__init__(*args, **kwargs) - if election_id: - self.fields["election"].queryset = Election.objects.filter( - id=election_id - ).all() - - -class ElectionForm(forms.ModelForm): - class Meta: - model = Election - fields = [ - "title", - "description", - "archived", - "start_candidature", - "end_candidature", - "start_date", - "end_date", - "edit_groups", - "view_groups", - "vote_groups", - "candidature_groups", - ] - widgets = { - "edit_groups": AutoCompleteSelectMultipleGroup, - "view_groups": AutoCompleteSelectMultipleGroup, - "vote_groups": AutoCompleteSelectMultipleGroup, - "candidature_groups": AutoCompleteSelectMultipleGroup, - } - - start_date = forms.DateTimeField( - label=_("Start date"), widget=SelectDateTime, required=True - ) - end_date = forms.DateTimeField( - label=_("End date"), widget=SelectDateTime, required=True - ) - start_candidature = forms.DateTimeField( - label=_("Start candidature"), widget=SelectDateTime, required=True - ) - end_candidature = forms.DateTimeField( - label=_("End candidature"), widget=SelectDateTime, required=True - ) - - # Display elections