From d3fbc65cdc951273918f32ab91b8caa656ae75f0 Mon Sep 17 00:00:00 2001 From: klmp200 Date: Wed, 7 Jun 2017 16:22:04 +0200 Subject: [PATCH 1/6] Pep8 for elections --- election/models.py | 60 ++++++++++------ election/tests.py | 23 +++--- election/urls.py | 30 +++++--- election/views.py | 175 +++++++++++++++++++++++++++++---------------- 4 files changed, 186 insertions(+), 102 deletions(-) diff --git a/election/models.py b/election/models.py index b2659424..d95f0a1e 100644 --- a/election/models.py +++ b/election/models.py @@ -1,9 +1,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from django.utils import timezone -from django.conf import settings -from datetime import timedelta from core.models import User, Group @@ -13,16 +11,26 @@ class Election(models.Model): """ title = models.CharField(_('title'), max_length=255) description = models.TextField(_('description'), null=True, blank=True) - start_candidature = models.DateTimeField(_('start candidature'), blank=False) + start_candidature = models.DateTimeField( + _('start candidature'), blank=False) end_candidature = models.DateTimeField(_('end candidature'), blank=False) start_date = models.DateTimeField(_('start date'), blank=False) end_date = models.DateTimeField(_('end date'), blank=False) - edit_groups = models.ManyToManyField(Group, related_name="editable_elections", verbose_name=_("edit groups"), blank=True) - view_groups = models.ManyToManyField(Group, related_name="viewable_elections", verbose_name=_("view groups"), blank=True) - vote_groups = models.ManyToManyField(Group, related_name="votable_elections", verbose_name=_("vote groups"), blank=True) - candidature_groups = models.ManyToManyField(Group, related_name="candidate_elections", verbose_name=_("candidature groups"), blank=True) - voters = models.ManyToManyField(User, verbose_name=('voters'), related_name='voted_elections') + edit_groups = models.ManyToManyField( + Group, related_name="editable_elections", + verbose_name=_("edit groups"), blank=True) + view_groups = models.ManyToManyField( + Group, related_name="viewable_elections", + verbose_name=_("view groups"), blank=True) + vote_groups = models.ManyToManyField( + Group, related_name="votable_elections", + verbose_name=_("vote groups"), blank=True) + candidature_groups = models.ManyToManyField( + Group, related_name="candidate_elections", + verbose_name=_("candidature groups"), blank=True) + voters = models.ManyToManyField(User, verbose_name=( + 'voters'), related_name='voted_elections') def __str__(self): return self.title @@ -39,7 +47,8 @@ class Election(models.Model): @property def is_candidature_active(self): now = timezone.now() - return bool(now <= self.end_candidature and now >= self.start_candidature) + return bool(now <= self.end_candidature and + now >= self.start_candidature) @property def is_vote_editable(self): @@ -77,7 +86,8 @@ class Role(models.Model): """ This class allows to create a new role avaliable for a candidature """ - election = models.ForeignKey(Election, related_name='roles', verbose_name=_("election")) + election = models.ForeignKey( + Election, related_name='roles', verbose_name=_("election")) title = models.CharField(_('title'), max_length=255) description = models.TextField(_('description'), null=True, blank=True) max_choice = models.IntegerField(_('max choice'), default=1) @@ -88,11 +98,13 @@ class Role(models.Model): non_blank = 0 for candidature in self.candidatures.all(): cand_results = {} - cand_results['vote'] = self.votes.filter(candidature=candidature).count() + cand_results['vote'] = self.votes.filter( + candidature=candidature).count() if total_vote == 0: cand_results['percent'] = 0 else: - cand_results['percent'] = cand_results['vote'] * 100 / total_vote + cand_results['percent'] = cand_results[ + 'vote'] * 100 / total_vote non_blank += cand_results['vote'] results[candidature.user.username] = cand_results results['total vote'] = total_vote @@ -100,7 +112,8 @@ class Role(models.Model): results['blank vote'] = {'vote': 0, 'percent': 0} else: results['blank vote'] = {'vote': total_vote - non_blank, - 'percent': (total_vote - non_blank) * 100 / total_vote} + 'percent': (total_vote - + non_blank) * 100 / total_vote} return results @property @@ -116,7 +129,8 @@ class ElectionList(models.Model): To allow per list vote """ title = models.CharField(_('title'), max_length=255) - election = models.ForeignKey(Election, related_name='election_lists', verbose_name=_("election")) + election = models.ForeignKey( + Election, related_name='election_lists', verbose_name=_("election")) def __str__(self): return self.title @@ -126,10 +140,14 @@ class Candidature(models.Model): """ This class is a component of responsability """ - role = models.ForeignKey(Role, related_name='candidatures', verbose_name=_("role")) - user = models.ForeignKey(User, verbose_name=_('user'), related_name='candidates', blank=True) + role = models.ForeignKey( + Role, related_name='candidatures', verbose_name=_("role")) + user = models.ForeignKey(User, verbose_name=_( + 'user'), related_name='candidates', blank=True) program = models.TextField(_('description'), null=True, blank=True) - election_list = models.ForeignKey(ElectionList, related_name='candidatures', verbose_name=_('election list')) + election_list = models.ForeignKey( + ElectionList, related_name='candidatures', + verbose_name=_('election list')) def can_be_edited_by(self, user): return (user == self.user) or user.can_edit(self.role.election) @@ -142,8 +160,10 @@ class Vote(models.Model): """ This class allows to vote for candidates """ - role = models.ForeignKey(Role, related_name='votes', verbose_name=_("role")) - candidature = models.ManyToManyField(Candidature, related_name='votes', verbose_name=_("candidature")) + role = models.ForeignKey( + Role, related_name='votes', verbose_name=_("role")) + candidature = models.ManyToManyField( + Candidature, related_name='votes', verbose_name=_("candidature")) def __str__(self): - return "Vote" \ No newline at end of file + return "Vote" diff --git a/election/tests.py b/election/tests.py index a2bd3f2f..91bc350f 100644 --- a/election/tests.py +++ b/election/tests.py @@ -1,11 +1,10 @@ -from django.test import Client, TestCase +from django.test import TestCase from django.core.urlresolvers import reverse from django.contrib.auth.models import Group from django.core.management import call_command from django.conf import settings -from datetime import date, datetime -from core.models import User, Group +from core.models import User from election.models import Election @@ -15,8 +14,10 @@ class MainElection(TestCase): self.election = Election.objects.all().first() self.public_group = Group.objects.get(id=settings.SITH_GROUP_PUBLIC_ID) - self.subscriber_group = Group.objects.get(name=settings.SITH_MAIN_MEMBERS_GROUP) - self.ae_board_group = Group.objects.get(name=settings.SITH_MAIN_BOARD_GROUP) + self.subscriber_group = Group.objects.get( + name=settings.SITH_MAIN_MEMBERS_GROUP) + self.ae_board_group = Group.objects.get( + name=settings.SITH_MAIN_BOARD_GROUP) self.sli = User.objects.get(username='sli') self.subscriber = User.objects.get(username='subscriber') self.public = User.objects.get(username='public') @@ -29,9 +30,9 @@ class ElectionDetailTest(MainElection): self.election.save() self.client.login(username=self.public.username, password='plop') response_get = self.client.get(reverse('election:detail', - args=str(self.election.id))) + args=str(self.election.id))) response_post = self.client.get(reverse('election:detail', - args=str(self.election.id))) + args=str(self.election.id))) self.assertTrue(response_get.status_code == 403) self.assertTrue(response_post.status_code == 403) self.election.view_groups.remove(self.subscriber_group) @@ -41,9 +42,9 @@ class ElectionDetailTest(MainElection): def test_permisson_granted(self): self.client.login(username=self.public.username, password='plop') response_get = self.client.get(reverse('election:detail', - args=str(self.election.id))) + args=str(self.election.id))) response_post = self.client.post(reverse('election:detail', - args=str(self.election.id))) + args=str(self.election.id))) self.assertFalse(response_get.status_code == 403) self.assertFalse(response_post.status_code == 403) self.assertTrue('La roue tourne' in str(response_get.content)) @@ -53,8 +54,8 @@ class ElectionUpdateView(MainElection): def test_permission_denied(self): self.client.login(username=self.subscriber.username, password='plop') response_get = self.client.get(reverse('election:update', - args=str(self.election.id))) + args=str(self.election.id))) response_post = self.client.post(reverse('election:update', - args=str(self.election.id))) + args=str(self.election.id))) self.assertTrue(response_get.status_code == 403) self.assertTrue(response_post.status_code == 403) diff --git a/election/urls.py b/election/urls.py index 8140cb49..fe94dab6 100644 --- a/election/urls.py +++ b/election/urls.py @@ -5,14 +5,24 @@ from election.views import * urlpatterns = [ url(r'^$', ElectionsListView.as_view(), name='list'), url(r'^add$', ElectionCreateView.as_view(), name='create'), - url(r'^(?P[0-9]+)/edit$', ElectionUpdateView.as_view(), name='update'), - url(r'^(?P[0-9]+)/list/add$', ElectionListCreateView.as_view(), name='create_list'), - url(r'^(?P[0-9]+)/role/create$', RoleCreateView.as_view(), name='create_role'), - url(r'^(?P[0-9]+)/role/edit$', RoleUpdateView.as_view(), name='update_role'), - url(r'^(?P[0-9]+)/role/delete$', RoleDeleteView.as_view(), name='delete_role'), - url(r'^(?P[0-9]+)/candidate/add$', CandidatureCreateView.as_view(), name='candidate'), - url(r'^(?P[0-9]+)/candidate/edit$', CandidatureUpdateView.as_view(), name='update_candidate'), - url(r'^(?P[0-9]+)/candidate/delete$', CandidatureDeleteView.as_view(), name='delete_candidate'), - url(r'^(?P[0-9]+)/vote$', VoteFormView.as_view(), name='vote'), - url(r'^(?P[0-9]+)/detail$', ElectionDetailView.as_view(), name='detail'), + url(r'^(?P[0-9]+)/edit$', + ElectionUpdateView.as_view(), name='update'), + url(r'^(?P[0-9]+)/list/add$', + ElectionListCreateView.as_view(), name='create_list'), + url(r'^(?P[0-9]+)/role/create$', + RoleCreateView.as_view(), name='create_role'), + url(r'^(?P[0-9]+)/role/edit$', + RoleUpdateView.as_view(), name='update_role'), + url(r'^(?P[0-9]+)/role/delete$', + RoleDeleteView.as_view(), name='delete_role'), + url(r'^(?P[0-9]+)/candidate/add$', + CandidatureCreateView.as_view(), name='candidate'), + url(r'^(?P[0-9]+)/candidate/edit$', + CandidatureUpdateView.as_view(), name='update_candidate'), + url(r'^(?P[0-9]+)/candidate/delete$', + CandidatureDeleteView.as_view(), name='delete_candidate'), + url(r'^(?P[0-9]+)/vote$', + VoteFormView.as_view(), name='vote'), + url(r'^(?P[0-9]+)/detail$', + ElectionDetailView.as_view(), name='detail'), ] diff --git a/election/views.py b/election/views.py index 2c4a8821..47230338 100644 --- a/election/views.py +++ b/election/views.py @@ -1,19 +1,16 @@ -from django.shortcuts import redirect, get_object_or_404 -from django.views.generic import ListView, DetailView, RedirectView -from django.views.generic.edit import UpdateView, CreateView, DeleteView, FormView -from django.core.urlresolvers import reverse_lazy, reverse +from django.shortcuts import get_object_or_404 +from django.views.generic import ListView, DetailView +from django.views.generic.edit import UpdateView, CreateView +from django.views.generic.edit import DeleteView, FormView +from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from django.forms.models import modelform_factory -from django.core.exceptions import PermissionDenied, ObjectDoesNotExist, ImproperlyConfigured -from django.db import DataError, transaction +from django.core.exceptions import PermissionDenied +from django.db import transaction from django.forms import CheckboxSelectMultiple -from django.utils import timezone -from django.conf import settings from django import forms -from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin +from core.views import CanViewMixin, CanEditMixin, CanCreateMixin from django.db.models.query import QuerySet -from django.views.generic.edit import FormMixin from core.views.forms import SelectDateTime from election.models import Election, Role, Candidature, ElectionList, Vote @@ -27,12 +24,16 @@ class LimitedCheckboxField(forms.ModelMultipleChoiceField): Used to replace ModelMultipleChoiceField but with automatic backend verification """ - def __init__(self, queryset, max_choice, required=True, widget=None, label=None, - initial=None, help_text='', *args, **kwargs): + + def __init__(self, queryset, max_choice, required=True, widget=None, + label=None, initial=None, help_text='', *args, **kwargs): self.max_choice = max_choice widget = forms.CheckboxSelectMultiple() - super(LimitedCheckboxField, self).__init__(queryset, None, required, widget, label, - initial, help_text, *args, **kwargs) + super(LimitedCheckboxField, self).__init__(queryset, + None, required, + widget, label, + initial, help_text, + *args, **kwargs) def clean(self, value): qs = super(LimitedCheckboxField, self).clean(value) @@ -41,7 +42,8 @@ class LimitedCheckboxField(forms.ModelMultipleChoiceField): def validate(self, qs): if qs.count() > self.max_choice: - raise forms.ValidationError(_("You have selected too much candidates."), code='invalid') + raise forms.ValidationError( + _("You have selected too much candidates."), code='invalid') # Forms @@ -56,15 +58,18 @@ class CandidateForm(forms.ModelForm): 'program': forms.Textarea } - user = AutoCompleteSelectField('users', label=_('User to candidate'), help_text=None, required=True) + user = AutoCompleteSelectField('users', label=_( + 'User to candidate'), help_text=None, required=True) def __init__(self, *args, **kwargs): election_id = kwargs.pop('election_id', None) can_edit = kwargs.pop('can_edit', False) super(CandidateForm, self).__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() + 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() @@ -76,10 +81,13 @@ class VoteForm(forms.Form): 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) + 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")) + self.fields[role.title] \ + = forms.ModelChoiceField(cand, required=False, + widget=forms.RadioSelect(), + empty_label=_("Blank vote")) class RoleForm(forms.ModelForm): @@ -92,33 +100,40 @@ class RoleForm(forms.ModelForm): election_id = kwargs.pop('election_id', None) super(RoleForm, self).__init__(*args, **kwargs) if election_id: - self.fields['election'].queryset = Election.objects.filter(id=election_id).all() + self.fields['election'].queryset = Election.objects.filter( + id=election_id).all() def clean(self): cleaned_data = super(RoleForm, self).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') + raise forms.ValidationError( + _("This role already exists for this election"), + code='invalid') class ElectionListForm(forms.ModelForm): class Meta: model = ElectionList - fields = ('title','election') + fields = ('title', 'election') def __init__(self, *args, **kwargs): election_id = kwargs.pop('election_id', None) super(ElectionListForm, self).__init__(*args, **kwargs) if election_id: - self.fields['election'].queryset = Election.objects.filter(id=election_id).all() + self.fields['election'].queryset = Election.objects.filter( + id=election_id).all() class ElectionForm(forms.ModelForm): class Meta: model = Election - fields = ['title', 'description', 'start_candidature', 'end_candidature', 'start_date', 'end_date', - 'edit_groups', 'view_groups', 'vote_groups', 'candidature_groups'] + fields = ['title', 'description', + 'start_candidature', 'end_candidature', + 'start_date', 'end_date', + 'edit_groups', 'view_groups', + 'vote_groups', 'candidature_groups'] widgets = { 'edit_groups': CheckboxSelectMultiple, 'view_groups': CheckboxSelectMultiple, @@ -127,10 +142,18 @@ class ElectionForm(forms.ModelForm): 'candidature_groups': CheckboxSelectMultiple } - start_date = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("Start date"), widget=SelectDateTime, required=True) - end_date = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("End date"), widget=SelectDateTime, required=True) - start_candidature = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("Start candidature"), widget=SelectDateTime, required=True) - end_candidature = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("End candidature"), widget=SelectDateTime, required=True) + start_date = forms.DateTimeField( + ['%Y-%m-%d %H:%M:%S'], label=_("Start date"), + widget=SelectDateTime, required=True) + end_date = forms.DateTimeField( + ['%Y-%m-%d %H:%M:%S'], label=_("End date"), + widget=SelectDateTime, required=True) + start_candidature = forms.DateTimeField( + ['%Y-%m-%d %H:%M:%S'], label=_("Start candidature"), + widget=SelectDateTime, required=True) + end_candidature = forms.DateTimeField( + ['%Y-%m-%d %H:%M:%S'], label=_("End candidature"), + widget=SelectDateTime, required=True) # Display elections @@ -179,7 +202,8 @@ class VoteFormView(CanCreateMixin, FormView): # If we have a multiple choice field if isinstance(election_data[role_title], QuerySet): if election_data[role_title].count() > 0: - vote = Vote(role=election_data[role_title].first().role) + vote = Vote(role=election_data[ + role_title].first().role) vote.save() for el in election_data[role_title]: vote.candidature.add(el) @@ -209,7 +233,8 @@ class VoteFormView(CanCreateMixin, FormView): return res def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', kwargs={'election_id': self.election.id}) + return reverse_lazy('election:detail', + kwargs={'election_id': self.election.id}) def get_context_data(self, **kwargs): """ Add additionnal data to the template """ @@ -232,7 +257,8 @@ class CandidatureCreateView(CanCreateMixin, CreateView): def dispatch(self, request, *arg, **kwargs): self.election = get_object_or_404(Election, pk=kwargs['election_id']) - return super(CandidatureCreateView, self).dispatch(request, *arg, **kwargs) + return super(CandidatureCreateView, + self).dispatch(request, *arg, **kwargs) def get_initial(self): init = {} @@ -252,7 +278,8 @@ class CandidatureCreateView(CanCreateMixin, CreateView): """ obj = form.instance obj.election = Election.objects.get(id=self.election.id) - if(obj.election.can_candidate(obj.user)) and (obj.user == self.request.user or self.can_edit): + if(obj.election.can_candidate(obj.user)) and \ + (obj.user == self.request.user or self.can_edit): return super(CreateView, self).form_valid(form) raise PermissionDenied @@ -262,7 +289,8 @@ class CandidatureCreateView(CanCreateMixin, CreateView): return kwargs def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', kwargs={'election_id': self.election.id}) + return reverse_lazy('election:detail', + kwargs={'election_id': self.election.id}) class ElectionCreateView(CanCreateMixin, CreateView): @@ -273,16 +301,19 @@ class ElectionCreateView(CanCreateMixin, CreateView): def dispatch(self, request, *args, **kwargs): if not request.user.is_subscribed: raise PermissionDenied - return super(ElectionCreateView, self).dispatch(request, *args, **kwargs) + return super(ElectionCreateView, + self).dispatch(request, *args, **kwargs) def form_valid(self, form): """ - Allow every users that had passed the dispatch to create an election + Allow every users that had passed the dispatch + to create an election """ return super(CreateView, self).form_valid(form) def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', kwargs={'election_id': self.object.id}) + return reverse_lazy('election:detail', + kwargs={'election_id': self.object.id}) class RoleCreateView(CanCreateMixin, CreateView): @@ -318,7 +349,8 @@ class RoleCreateView(CanCreateMixin, CreateView): return kwargs def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', kwargs={'election_id': self.object.election.id}) + return reverse_lazy('election:detail', + kwargs={'election_id': self.object.election.id}) class ElectionListCreateView(CanCreateMixin, CreateView): @@ -330,7 +362,8 @@ class ElectionListCreateView(CanCreateMixin, CreateView): self.election = get_object_or_404(Election, pk=kwargs['election_id']) if not self.election.is_vote_editable: raise PermissionDenied - return super(ElectionListCreateView, self).dispatch(request, *arg, **kwargs) + return super(ElectionListCreateView, + self).dispatch(request, *arg, **kwargs) def get_initial(self): init = {} @@ -357,7 +390,8 @@ class ElectionListCreateView(CanCreateMixin, CreateView): raise PermissionDenied def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', kwargs={'election_id': self.object.election.id}) + return reverse_lazy('election:detail', + kwargs={'election_id': self.object.election.id}) # Update view @@ -371,21 +405,30 @@ class ElectionUpdateView(CanEditMixin, UpdateView): def get_initial(self): init = {} try: - init['start_date'] = self.object.start_date.strftime('%Y-%m-%d %H:%M:%S') - except:pass + init['start_date'] = self.object.start_date.strftime( + '%Y-%m-%d %H:%M:%S') + except Exception: + pass try: - init['end_date'] = self.object.end_date.strftime('%Y-%m-%d %H:%M:%S') - except:pass + init['end_date'] = self.object.end_date.strftime( + '%Y-%m-%d %H:%M:%S') + except Exception: + pass try: - init['start_candidature'] = self.object.start_candidature.strftime('%Y-%m-%d %H:%M:%S') - except:pass + init['start_candidature'] = self.object.start_candidature.strftime( + '%Y-%m-%d %H:%M:%S') + except Exception: + pass try: - init['end_candidature'] = self.object.end_candidature.strftime('%Y-%m-%d %H:%M:%S') - except:pass + init['end_candidature'] = self.object.end_candidature.strftime( + '%Y-%m-%d %H:%M:%S') + except Exception: + pass return init def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', kwargs={'election_id': self.object.id}) + return reverse_lazy('election:detail', + kwargs={'election_id': self.object.id}) class CandidatureUpdateView(CanEditMixin, UpdateView): @@ -398,7 +441,8 @@ class CandidatureUpdateView(CanEditMixin, UpdateView): self.object = self.get_object() if not self.object.role.election.is_vote_editable: raise PermissionDenied - return super(CandidatureUpdateView, self).dispatch(request, *arg, **kwargs) + return super(CandidatureUpdateView, + self).dispatch(request, *arg, **kwargs) def remove_fields(self): self.form.fields.pop('role', None) @@ -411,7 +455,8 @@ class CandidatureUpdateView(CanEditMixin, UpdateView): def post(self, request, *args, **kwargs): self.form = self.get_form() self.remove_fields() - if request.user.is_authenticated() and request.user.can_edit(self.object) and self.form.is_valid(): + if request.user.is_authenticated() and \ + request.user.can_edit(self.object) and self.form.is_valid(): return super(CandidatureUpdateView, self).form_valid(self.form) return self.form_invalid(self.form) @@ -421,7 +466,9 @@ class CandidatureUpdateView(CanEditMixin, UpdateView): return kwargs def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', kwargs={'election_id': self.object.role.election.id}) + return reverse_lazy('election:detail', + kwargs={'election_id': + self.object.role.election.id}) class RoleUpdateView(CanEditMixin, UpdateView): @@ -449,7 +496,8 @@ class RoleUpdateView(CanEditMixin, UpdateView): self.object = self.get_object() self.form = self.get_form() self.remove_fields() - if request.user.is_authenticated() and request.user.can_edit(self.object) and self.form.is_valid(): + if request.user.is_authenticated() and \ + request.user.can_edit(self.object) and self.form.is_valid(): return super(RoleUpdateView, self).form_valid(self.form) return self.form_invalid(self.form) @@ -459,7 +507,8 @@ class RoleUpdateView(CanEditMixin, UpdateView): return kwargs def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', kwargs={'election_id': self.object.election.id}) + return reverse_lazy('election:detail', + kwargs={'election_id': self.object.election.id}) # Delete Views @@ -472,12 +521,15 @@ class CandidatureDeleteView(CanEditMixin, DeleteView): def dispatch(self, request, *arg, **kwargs): self.object = self.get_object() self.election = self.object.role.election - if not self.election.can_candidate or not self.election.is_vote_editable: + if not self.election.can_candidate \ + or not self.election.is_vote_editable: raise PermissionDenied - return super(CandidatureDeleteView, self).dispatch(request, *arg, **kwargs) + return super(CandidatureDeleteView, + self).dispatch(request, *arg, **kwargs) def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', kwargs={'election_id': self.election.id}) + return reverse_lazy('election:detail', + kwargs={'election_id': self.election.id}) class RoleDeleteView(CanEditMixin, DeleteView): @@ -493,4 +545,5 @@ class RoleDeleteView(CanEditMixin, DeleteView): return super(RoleDeleteView, self).dispatch(request, *arg, **kwargs) def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', kwargs={'election_id': self.election.id}) + return reverse_lazy('election:detail', + kwargs={'election_id': self.election.id}) From 0076c9cdb489108f8f4ca83dc1a3386ba0627736 Mon Sep 17 00:00:00 2001 From: klmp200 Date: Wed, 7 Jun 2017 16:43:50 +0200 Subject: [PATCH 2/6] Macro for pagination --- core/templates/core/macros.jinja | 20 +++++++++++++++++++ .../templates/counter/cash_summary_list.jinja | 20 ++----------------- .../templates/election/election_list.jinja | 4 ++++ election/views.py | 2 ++ 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/core/templates/core/macros.jinja b/core/templates/core/macros.jinja index 244617c5..9be68685 100644 --- a/core/templates/core/macros.jinja +++ b/core/templates/core/macros.jinja @@ -72,3 +72,23 @@ {% trans %}Delete{% endtrans %} {% endif %} {% endmacro %} + +{% macro paginate(page_obj, paginator) %} + {% if page_obj.has_previous() %} + {% trans %}Previous{% endtrans %} + {% else %} + {% trans %}Previous{% endtrans %} + {% endif %} + {% for i in paginator.page_range %} + {% if page_obj.number == i %} + {{ i }} ({% trans %}current{% endtrans %}) + {% else %} + {{ i }} + {% endif %} + {% endfor %} + {% if page_obj.has_next() %} + {% trans %}Next{% endtrans %} + {% else %} + {% trans %}Next{% endtrans %} + {% endif %} +{% endmacro %} \ No newline at end of file diff --git a/counter/templates/counter/cash_summary_list.jinja b/counter/templates/counter/cash_summary_list.jinja index a9432d06..80f80f81 100644 --- a/counter/templates/counter/cash_summary_list.jinja +++ b/counter/templates/counter/cash_summary_list.jinja @@ -1,5 +1,5 @@ {% extends "core/base.jinja" %} -{% from 'core/macros.jinja' import user_profile_link %} +{% from 'core/macros.jinja' import user_profile_link, paginate %} {% block title %} {% trans %}Cash register summary list{% endtrans %} @@ -57,23 +57,7 @@
{% if is_paginated %} - {% if page_obj.has_previous() %} - {% trans %}Previous{% endtrans %} - {% else %} - {% trans %}Previous{% endtrans %} - {% endif %} - {% for i in paginator.page_range %} - {% if page_obj.number == i %} - {{ i }} ({% trans %}current{% endtrans %}) - {% else %} - {{ i }} - {% endif %} - {% endfor %} - {% if page_obj.has_next() %} - {% trans %}Next{% endtrans %} - {% else %} - {% trans %}Next{% endtrans %} - {% endif %} + {{ paginate(page_obj, paginator) }} {% endif %} {% else %} {% trans %}There is no cash register summary in this website.{% endtrans %} diff --git a/election/templates/election/election_list.jinja b/election/templates/election/election_list.jinja index 3bcb0110..9e06eb74 100644 --- a/election/templates/election/election_list.jinja +++ b/election/templates/election/election_list.jinja @@ -1,4 +1,5 @@ {% extends "core/base.jinja" %} +{% from 'core/macros.jinja' import paginate %} {% block title %} {%- trans %}Election list{% endtrans %} @@ -44,5 +45,8 @@

{{ election.description }}

{%- endfor %} +{% if is_paginated %} + {{ paginate(page_obj, paginator) }} +{% endif %} {%- endblock %} diff --git a/election/views.py b/election/views.py index 47230338..80cc1499 100644 --- a/election/views.py +++ b/election/views.py @@ -164,6 +164,8 @@ class ElectionsListView(CanViewMixin, ListView): A list with all responsabilities and their candidates """ model = Election + ordering = ["-id"] + paginate_by = 10 template_name = 'election/election_list.jinja' From c4389bb9cd0153c4315212bf16613404d7ee6e22 Mon Sep 17 00:00:00 2001 From: klmp200 Date: Wed, 7 Jun 2017 17:33:46 +0200 Subject: [PATCH 3/6] Add a way for admin to delete elections and add archive system --- core/templates/core/user_tools.jinja | 1 + election/migrations/0002_election_archived.py | 19 ++++ election/models.py | 1 + .../templates/election/election_detail.jinja | 3 + election/urls.py | 4 + election/views.py | 37 +++++- locale/fr/LC_MESSAGES/django.po | 107 +++++++++--------- 7 files changed, 119 insertions(+), 53 deletions(-) create mode 100644 election/migrations/0002_election_archived.py diff --git a/core/templates/core/user_tools.jinja b/core/templates/core/user_tools.jinja index f23cf6dd..1074e64e 100644 --- a/core/templates/core/user_tools.jinja +++ b/core/templates/core/user_tools.jinja @@ -103,6 +103,7 @@

{% trans %}Elections{% endtrans %}

  • {% trans %}See available elections{% endtrans %}
  • +
  • {% trans %}See archived elections{% endtrans %}
  • {%- if user.is_subscribed -%}
  • {% trans %}Create a new election{% endtrans %}
  • {%- endif -%} diff --git a/election/migrations/0002_election_archived.py b/election/migrations/0002_election_archived.py new file mode 100644 index 00000000..fda74ef0 --- /dev/null +++ b/election/migrations/0002_election_archived.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('election', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='election', + name='archived', + field=models.BooleanField(verbose_name='archived', default=False), + ), + ] diff --git a/election/models.py b/election/models.py index d95f0a1e..5594b1e5 100644 --- a/election/models.py +++ b/election/models.py @@ -31,6 +31,7 @@ class Election(models.Model): verbose_name=_("candidature groups"), blank=True) voters = models.ManyToManyField(User, verbose_name=( 'voters'), related_name='voted_elections') + archived = models.BooleanField(_("archived"), default=False) def __str__(self): return self.title diff --git a/election/templates/election/election_detail.jinja b/election/templates/election/election_detail.jinja index 5f2b4e57..dd5feff7 100644 --- a/election/templates/election/election_detail.jinja +++ b/election/templates/election/election_detail.jinja @@ -373,6 +373,9 @@ th { {% endif %} {% trans %}Edit{% endtrans %} {%- endif %} + {%- if user.is_root %} + {% trans %}Delete{% endtrans %} + {%- endif %} {% endblock %} diff --git a/election/urls.py b/election/urls.py index fe94dab6..e9c813d7 100644 --- a/election/urls.py +++ b/election/urls.py @@ -4,9 +4,13 @@ from election.views import * urlpatterns = [ url(r'^$', ElectionsListView.as_view(), name='list'), + url(r'^archived$', + ElectionListArchivedView.as_view(), name='list_archived'), url(r'^add$', ElectionCreateView.as_view(), name='create'), url(r'^(?P[0-9]+)/edit$', ElectionUpdateView.as_view(), name='update'), + url(r'^(?P[0-9]+)/delete$', + ElectionDeleteView.as_view(), name='delete'), url(r'^(?P[0-9]+)/list/add$', ElectionListCreateView.as_view(), name='create_list'), url(r'^(?P[0-9]+)/role/create$', diff --git a/election/views.py b/election/views.py index 80cc1499..dbe3d694 100644 --- a/election/views.py +++ b/election/views.py @@ -129,7 +129,7 @@ class ElectionListForm(forms.ModelForm): class ElectionForm(forms.ModelForm): class Meta: model = Election - fields = ['title', 'description', + fields = ['title', 'description', 'archived', 'start_candidature', 'end_candidature', 'start_date', 'end_date', 'edit_groups', 'view_groups', @@ -161,13 +161,31 @@ class ElectionForm(forms.ModelForm): class ElectionsListView(CanViewMixin, ListView): """ - A list with all responsabilities and their candidates + A list of all non archived elections visible """ model = Election ordering = ["-id"] paginate_by = 10 template_name = 'election/election_list.jinja' + def get_queryset(self): + return super(ElectionsListView, + self).get_queryset().filter(archived=False).all() + + +class ElectionListArchivedView(CanViewMixin, ListView): + """ + A list of all archived elections visible + """ + model = Election + ordering = ["-id"] + paginate_by = 10 + template_name = 'election/election_list.jinja' + + def get_queryset(self): + return super(ElectionListArchivedView, + self).get_queryset().filter(archived=True).all() + class ElectionDetailView(CanViewMixin, DetailView): """ @@ -515,6 +533,21 @@ class RoleUpdateView(CanEditMixin, UpdateView): # Delete Views +class ElectionDeleteView(DeleteView): + model = Election + template_name = 'core/delete_confirm.jinja' + pk_url_kwarg = 'election_id' + + def dispatch(self, request, *args, **kwargs): + if request.user.is_root: + return super(ElectionDeleteView, + self).dispatch(request, *args, **kwargs) + raise PermissionDenied + + def get_success_url(self, **kwargs): + return reverse_lazy('election:list') + + class CandidatureDeleteView(CanEditMixin, DeleteView): model = Candidature template_name = 'core/delete_confirm.jinja' diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index cc14ecd4..7aa41665 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-06-06 23:25+0200\n" +"POT-Creation-Date: 2017-06-07 17:32+0200\n" "PO-Revision-Date: 2016-07-18\n" "Last-Translator: Skia \n" "Language-Team: AE info \n" @@ -88,12 +88,12 @@ msgid "%(club_account)s on %(bank_account)s" msgstr "%(club_account)s sur %(bank_account)s" #: accounting/models.py:192 club/models.py:184 counter/models.py:433 -#: election/models.py:18 launderette/models.py:144 +#: election/models.py:17 launderette/models.py:144 msgid "start date" msgstr "date de début" #: accounting/models.py:193 club/models.py:185 counter/models.py:434 -#: election/models.py:19 +#: election/models.py:18 msgid "end date" msgstr "date de fin" @@ -335,6 +335,7 @@ msgstr "Compte en banque : " #: counter/templates/counter/last_ops.jinja:59 #: election/templates/election/election_detail.jinja:280 #: election/templates/election/election_detail.jinja:329 +#: election/templates/election/election_detail.jinja:377 #: forum/templates/forum/macros.jinja:21 forum/templates/forum/macros.jinja:123 #: launderette/templates/launderette/launderette_admin.jinja:16 #: launderette/views.py:178 sas/templates/sas/album.jinja:26 @@ -830,19 +831,19 @@ msgid "A club with that unix_name already exists" msgstr "Un club avec ce nom UNIX existe déjà." #: club/models.py:182 counter/models.py:431 counter/models.py:448 -#: eboutic/models.py:38 eboutic/models.py:71 election/models.py:130 +#: eboutic/models.py:38 eboutic/models.py:71 election/models.py:147 #: launderette/models.py:111 launderette/models.py:148 sas/models.py:156 msgid "user" msgstr "nom d'utilisateur" -#: club/models.py:186 core/models.py:169 election/models.py:129 -#: election/models.py:145 +#: club/models.py:186 core/models.py:169 election/models.py:145 +#: election/models.py:165 msgid "role" msgstr "rôle" #: club/models.py:188 core/models.py:61 counter/models.py:101 -#: counter/models.py:126 election/models.py:15 election/models.py:82 -#: election/models.py:131 forum/models.py:51 forum/models.py:184 +#: counter/models.py:126 election/models.py:13 election/models.py:93 +#: election/models.py:148 forum/models.py:51 forum/models.py:184 msgid "description" msgstr "description" @@ -1069,6 +1070,7 @@ msgstr "Date de début" #: club/views.py:196 com/views.py:123 counter/views.py:1020 #: election/views.py:131 subscription/views.py:50 +#: election/views.py:149 msgid "End date" msgstr "Date de fin" @@ -1109,8 +1111,8 @@ msgstr "Hebdomadaire" msgid "Call" msgstr "Appel" -#: com/models.py:60 com/models.py:102 com/models.py:149 election/models.py:14 -#: election/models.py:81 election/models.py:118 forum/models.py:187 +#: com/models.py:60 com/models.py:102 com/models.py:149 election/models.py:12 +#: election/models.py:92 election/models.py:132 forum/models.py:187 #: forum/models.py:234 msgid "title" msgstr "titre" @@ -1416,6 +1418,7 @@ msgid "Alert message" msgstr "Message d'alerte" #: com/views.py:122 election/views.py:130 subscription/views.py:47 +#: com/views.py:122 election/views.py:146 msgid "Start date" msgstr "Date de début" @@ -2145,6 +2148,18 @@ msgstr "Créneau" msgid "Tokens" msgstr "Jetons" +#: core/templates/core/macros.jinja:78 core/templates/core/macros.jinja:80 +msgid "Previous" +msgstr "Précédent" + +#: core/templates/core/macros.jinja:84 +msgid "current" +msgstr "actuel" + +#: core/templates/core/macros.jinja:90 core/templates/core/macros.jinja:92 +msgid "Next" +msgstr "Suivant" + #: core/templates/core/new_user_email.jinja:2 msgid "" "You're receiving this email because you subscribed to the UTBM student " @@ -2698,6 +2713,10 @@ msgstr "Élections" msgid "See available elections" msgstr "Voir les élections disponibles" +#: core/templates/core/user_tools.jinja:105 +msgid "See archived elections" +msgstr "Voir les élections archivées" + #: core/templates/core/user_tools.jinja:107 msgid "Create a new election" msgstr "Créer une nouvelle élection" @@ -2834,7 +2853,7 @@ msgstr "produit parent" msgid "buying groups" msgstr "groupe d'achat" -#: counter/models.py:140 +#: counter/models.py:140 election/models.py:34 msgid "archived" msgstr "archivé" @@ -3035,21 +3054,7 @@ msgstr "Coffre vidé" msgid "yes" msgstr "oui" -#: counter/templates/counter/cash_summary_list.jinja:61 #: counter/templates/counter/cash_summary_list.jinja:63 -msgid "Previous" -msgstr "Précédent" - -#: counter/templates/counter/cash_summary_list.jinja:67 -msgid "current" -msgstr "actuel" - -#: counter/templates/counter/cash_summary_list.jinja:73 -#: counter/templates/counter/cash_summary_list.jinja:75 -msgid "Next" -msgstr "Suivant" - -#: counter/templates/counter/cash_summary_list.jinja:79 msgid "There is no cash register summary in this website." msgstr "Il n'y a pas de relevé de caisse dans ce site web." @@ -3434,43 +3439,43 @@ msgstr "Retourner à l'eboutic" msgid "You do not have enough money to buy the basket" msgstr "Vous n'avez pas assez d'argent pour acheter le panier" -#: election/models.py:16 +#: election/models.py:15 msgid "start candidature" msgstr "début des candidatures" -#: election/models.py:17 +#: election/models.py:16 msgid "end candidature" msgstr "fin des candidatures" -#: election/models.py:21 +#: election/models.py:22 msgid "edit groups" msgstr "groupe d'édition" -#: election/models.py:22 +#: election/models.py:25 msgid "view groups" msgstr "groupe de vue" -#: election/models.py:23 +#: election/models.py:28 msgid "vote groups" msgstr "groupe de vote" -#: election/models.py:24 +#: election/models.py:31 msgid "candidature groups" msgstr "groupe de candidature" -#: election/models.py:80 election/models.py:119 +#: election/models.py:91 election/models.py:134 msgid "election" msgstr "élection" -#: election/models.py:83 +#: election/models.py:94 msgid "max choice" msgstr "nombre de choix maxi" -#: election/models.py:132 +#: election/models.py:151 msgid "election list" msgstr "liste électorale" -#: election/models.py:146 +#: election/models.py:167 msgid "candidature" msgstr "candidature" @@ -3498,10 +3503,10 @@ msgstr "Les votes ouvriront " #: election/templates/election/election_detail.jinja:243 #: election/templates/election/election_detail.jinja:247 -#: election/templates/election/election_list.jinja:31 -#: election/templates/election/election_list.jinja:34 -#: election/templates/election/election_list.jinja:39 -#: election/templates/election/election_list.jinja:42 +#: election/templates/election/election_list.jinja:32 +#: election/templates/election/election_list.jinja:35 +#: election/templates/election/election_list.jinja:40 +#: election/templates/election/election_list.jinja:43 #: forum/templates/forum/macros.jinja:137 msgid " at " msgstr " à " @@ -3518,7 +3523,7 @@ msgstr "Vous avez déjà soumis votre vote." msgid "You have voted in this election." msgstr "Vous avez déjà voté pour cette élection." -#: election/templates/election/election_detail.jinja:266 election/views.py:82 +#: election/templates/election/election_detail.jinja:266 election/views.py:90 msgid "Blank vote" msgstr "Vote blanc" @@ -3556,44 +3561,44 @@ msgstr "Ajouter une nouvelle liste" msgid "Add a new role" msgstr "Ajouter un nouveau rôle" -#: election/templates/election/election_list.jinja:4 +#: election/templates/election/election_list.jinja:5 msgid "Election list" msgstr "Liste des élections" -#: election/templates/election/election_list.jinja:21 +#: election/templates/election/election_list.jinja:22 msgid "Current elections" msgstr "Élections actuelles" -#: election/templates/election/election_list.jinja:29 +#: election/templates/election/election_list.jinja:30 msgid "Applications open from" msgstr "Candidatures ouvertes à partir du" -#: election/templates/election/election_list.jinja:32 -#: election/templates/election/election_list.jinja:40 +#: election/templates/election/election_list.jinja:33 +#: election/templates/election/election_list.jinja:41 msgid "to" msgstr "au" -#: election/templates/election/election_list.jinja:37 +#: election/templates/election/election_list.jinja:38 msgid "Polls open from" msgstr "Votes ouverts du" -#: election/views.py:44 +#: election/views.py:46 msgid "You have selected too much candidates." msgstr "Vous avez sélectionné trop de candidats." -#: election/views.py:59 +#: election/views.py:62 msgid "User to candidate" msgstr "Utilisateur se présentant" -#: election/views.py:102 +#: election/views.py:112 msgid "This role already exists for this election" msgstr "Ce rôle existe déjà pour cette élection" -#: election/views.py:132 +#: election/views.py:152 msgid "Start candidature" msgstr "Début des candidatures" -#: election/views.py:133 +#: election/views.py:155 msgid "End candidature" msgstr "Fin des candidatures" From 41a9bf9953d8f944239118656f190987668c4ea3 Mon Sep 17 00:00:00 2001 From: klmp200 Date: Wed, 7 Jun 2017 18:49:24 +0200 Subject: [PATCH 4/6] Elections : Fix tests, cleaned urls and add nice description --- .../templates/election/election_detail.jinja | 1 + election/tests.py | 3 +- election/urls.py | 36 +++++++------------ 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/election/templates/election/election_detail.jinja b/election/templates/election/election_detail.jinja index dd5feff7..78cc5040 100644 --- a/election/templates/election/election_detail.jinja +++ b/election/templates/election/election_detail.jinja @@ -279,6 +279,7 @@ th { {% trans %}Edit{% endtrans %} {% trans %}Delete{% endtrans %} {%- endif -%} +
    {{ role.description }} {%- if role.max_choice > 1 and not election.has_voted(user) and election.can_vote(user) %} {% trans %}You may choose up to{% endtrans %} {{ role.max_choice }} {% trans %}people.{% endtrans %} {%- endif %} diff --git a/election/tests.py b/election/tests.py index 91bc350f..61ad1226 100644 --- a/election/tests.py +++ b/election/tests.py @@ -1,10 +1,9 @@ from django.test import TestCase from django.core.urlresolvers import reverse -from django.contrib.auth.models import Group from django.core.management import call_command from django.conf import settings -from core.models import User +from core.models import User, Group from election.models import Election diff --git a/election/urls.py b/election/urls.py index e9c813d7..7c99e8e8 100644 --- a/election/urls.py +++ b/election/urls.py @@ -4,29 +4,17 @@ from election.views import * urlpatterns = [ url(r'^$', ElectionsListView.as_view(), name='list'), - url(r'^archived$', - ElectionListArchivedView.as_view(), name='list_archived'), + url(r'^archived$', ElectionListArchivedView.as_view(), name='list_archived'), url(r'^add$', ElectionCreateView.as_view(), name='create'), - url(r'^(?P[0-9]+)/edit$', - ElectionUpdateView.as_view(), name='update'), - url(r'^(?P[0-9]+)/delete$', - ElectionDeleteView.as_view(), name='delete'), - url(r'^(?P[0-9]+)/list/add$', - ElectionListCreateView.as_view(), name='create_list'), - url(r'^(?P[0-9]+)/role/create$', - RoleCreateView.as_view(), name='create_role'), - url(r'^(?P[0-9]+)/role/edit$', - RoleUpdateView.as_view(), name='update_role'), - url(r'^(?P[0-9]+)/role/delete$', - RoleDeleteView.as_view(), name='delete_role'), - url(r'^(?P[0-9]+)/candidate/add$', - CandidatureCreateView.as_view(), name='candidate'), - url(r'^(?P[0-9]+)/candidate/edit$', - CandidatureUpdateView.as_view(), name='update_candidate'), - url(r'^(?P[0-9]+)/candidate/delete$', - CandidatureDeleteView.as_view(), name='delete_candidate'), - url(r'^(?P[0-9]+)/vote$', - VoteFormView.as_view(), name='vote'), - url(r'^(?P[0-9]+)/detail$', - ElectionDetailView.as_view(), name='detail'), + url(r'^(?P[0-9]+)/edit$', ElectionUpdateView.as_view(), name='update'), + url(r'^(?P[0-9]+)/delete$', ElectionDeleteView.as_view(), name='delete'), + url(r'^(?P[0-9]+)/list/add$', ElectionListCreateView.as_view(), name='create_list'), + url(r'^(?P[0-9]+)/role/create$', RoleCreateView.as_view(), name='create_role'), + url(r'^(?P[0-9]+)/role/edit$', RoleUpdateView.as_view(), name='update_role'), + url(r'^(?P[0-9]+)/role/delete$', RoleDeleteView.as_view(), name='delete_role'), + url(r'^(?P[0-9]+)/candidate/add$', CandidatureCreateView.as_view(), name='candidate'), + url(r'^(?P[0-9]+)/candidate/edit$', CandidatureUpdateView.as_view(), name='update_candidate'), + url(r'^(?P[0-9]+)/candidate/delete$', CandidatureDeleteView.as_view(), name='delete_candidate'), + url(r'^(?P[0-9]+)/vote$', VoteFormView.as_view(), name='vote'), + url(r'^(?P[0-9]+)/detail$', ElectionDetailView.as_view(), name='detail'), ] From b6a68fa09077b6cdb5d8bfc9ede786b3b26e7ee2 Mon Sep 17 00:00:00 2001 From: klmp200 Date: Wed, 7 Jun 2017 19:16:55 +0200 Subject: [PATCH 5/6] Fix some ugly lines --- election/models.py | 45 +++++++--------- election/views.py | 124 ++++++++++++++++----------------------------- 2 files changed, 60 insertions(+), 109 deletions(-) diff --git a/election/models.py b/election/models.py index 5594b1e5..57363125 100644 --- a/election/models.py +++ b/election/models.py @@ -11,8 +11,7 @@ class Election(models.Model): """ title = models.CharField(_('title'), max_length=255) description = models.TextField(_('description'), null=True, blank=True) - start_candidature = models.DateTimeField( - _('start candidature'), blank=False) + start_candidature = models.DateTimeField(_('start candidature'), blank=False) end_candidature = models.DateTimeField(_('end candidature'), blank=False) start_date = models.DateTimeField(_('start date'), blank=False) end_date = models.DateTimeField(_('end date'), blank=False) @@ -20,17 +19,20 @@ class Election(models.Model): edit_groups = models.ManyToManyField( Group, related_name="editable_elections", verbose_name=_("edit groups"), blank=True) + view_groups = models.ManyToManyField( Group, related_name="viewable_elections", verbose_name=_("view groups"), blank=True) + vote_groups = models.ManyToManyField( Group, related_name="votable_elections", verbose_name=_("vote groups"), blank=True) + candidature_groups = models.ManyToManyField( Group, related_name="candidate_elections", verbose_name=_("candidature groups"), blank=True) - voters = models.ManyToManyField(User, verbose_name=( - 'voters'), related_name='voted_elections') + + voters = models.ManyToManyField(User, verbose_name=('voters'), related_name='voted_elections') archived = models.BooleanField(_("archived"), default=False) def __str__(self): @@ -48,8 +50,7 @@ class Election(models.Model): @property def is_candidature_active(self): now = timezone.now() - return bool(now <= self.end_candidature and - now >= self.start_candidature) + return bool(now <= self.end_candidature and now >= self.start_candidature) @property def is_vote_editable(self): @@ -87,8 +88,7 @@ class Role(models.Model): """ This class allows to create a new role avaliable for a candidature """ - election = models.ForeignKey( - Election, related_name='roles', verbose_name=_("election")) + election = models.ForeignKey(Election, related_name='roles', verbose_name=_("election")) title = models.CharField(_('title'), max_length=255) description = models.TextField(_('description'), null=True, blank=True) max_choice = models.IntegerField(_('max choice'), default=1) @@ -99,22 +99,18 @@ class Role(models.Model): non_blank = 0 for candidature in self.candidatures.all(): cand_results = {} - cand_results['vote'] = self.votes.filter( - candidature=candidature).count() + cand_results['vote'] = self.votes.filter(candidature=candidature).count() if total_vote == 0: cand_results['percent'] = 0 else: - cand_results['percent'] = cand_results[ - 'vote'] * 100 / total_vote + cand_results['percent'] = cand_results['vote'] * 100 / total_vote non_blank += cand_results['vote'] results[candidature.user.username] = cand_results results['total vote'] = total_vote if total_vote == 0: results['blank vote'] = {'vote': 0, 'percent': 0} else: - results['blank vote'] = {'vote': total_vote - non_blank, - 'percent': (total_vote - - non_blank) * 100 / total_vote} + results['blank vote'] = {'vote': total_vote - non_blank, 'percent': (total_vote - non_blank) * 100 / total_vote} return results @property @@ -130,8 +126,7 @@ class ElectionList(models.Model): To allow per list vote """ title = models.CharField(_('title'), max_length=255) - election = models.ForeignKey( - Election, related_name='election_lists', verbose_name=_("election")) + election = models.ForeignKey(Election, related_name='election_lists', verbose_name=_("election")) def __str__(self): return self.title @@ -141,14 +136,10 @@ class Candidature(models.Model): """ This class is a component of responsability """ - role = models.ForeignKey( - Role, related_name='candidatures', verbose_name=_("role")) - user = models.ForeignKey(User, verbose_name=_( - 'user'), related_name='candidates', blank=True) + role = models.ForeignKey(Role, related_name='candidatures', verbose_name=_("role")) + user = models.ForeignKey(User, verbose_name=_('user'), related_name='candidates', blank=True) program = models.TextField(_('description'), null=True, blank=True) - election_list = models.ForeignKey( - ElectionList, related_name='candidatures', - verbose_name=_('election list')) + election_list = models.ForeignKey(ElectionList, related_name='candidatures', verbose_name=_('election list')) def can_be_edited_by(self, user): return (user == self.user) or user.can_edit(self.role.election) @@ -161,10 +152,8 @@ class Vote(models.Model): """ This class allows to vote for candidates """ - role = models.ForeignKey( - Role, related_name='votes', verbose_name=_("role")) - candidature = models.ManyToManyField( - Candidature, related_name='votes', verbose_name=_("candidature")) + role = models.ForeignKey(Role, related_name='votes', verbose_name=_("role")) + candidature = models.ManyToManyField(Candidature, related_name='votes', verbose_name=_("candidature")) def __str__(self): return "Vote" diff --git a/election/views.py b/election/views.py index dbe3d694..7fd9907d 100644 --- a/election/views.py +++ b/election/views.py @@ -29,8 +29,7 @@ class LimitedCheckboxField(forms.ModelMultipleChoiceField): label=None, initial=None, help_text='', *args, **kwargs): self.max_choice = max_choice widget = forms.CheckboxSelectMultiple() - super(LimitedCheckboxField, self).__init__(queryset, - None, required, + super(LimitedCheckboxField, self).__init__(queryset, None, required, widget, label, initial, help_text, *args, **kwargs) @@ -42,8 +41,7 @@ class LimitedCheckboxField(forms.ModelMultipleChoiceField): def validate(self, qs): if qs.count() > self.max_choice: - raise forms.ValidationError( - _("You have selected too much candidates."), code='invalid') + raise forms.ValidationError(_("You have selected too much candidates."), code='invalid') # Forms @@ -66,10 +64,8 @@ class CandidateForm(forms.ModelForm): can_edit = kwargs.pop('can_edit', False) super(CandidateForm, self).__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() + 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() @@ -81,13 +77,11 @@ class VoteForm(forms.Form): 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) + 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")) + self.fields[role.title] = forms.ModelChoiceField(cand, required=False, + widget=forms.RadioSelect(), + empty_label=_("Blank vote")) class RoleForm(forms.ModelForm): @@ -109,8 +103,7 @@ class RoleForm(forms.ModelForm): 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') + _("This role already exists for this election"), code='invalid') class ElectionListForm(forms.ModelForm): @@ -122,8 +115,7 @@ class ElectionListForm(forms.ModelForm): election_id = kwargs.pop('election_id', None) super(ElectionListForm, self).__init__(*args, **kwargs) if election_id: - self.fields['election'].queryset = Election.objects.filter( - id=election_id).all() + self.fields['election'].queryset = Election.objects.filter(id=election_id).all() class ElectionForm(forms.ModelForm): @@ -142,18 +134,14 @@ class ElectionForm(forms.ModelForm): 'candidature_groups': CheckboxSelectMultiple } - start_date = forms.DateTimeField( - ['%Y-%m-%d %H:%M:%S'], label=_("Start date"), - widget=SelectDateTime, required=True) - end_date = forms.DateTimeField( - ['%Y-%m-%d %H:%M:%S'], label=_("End date"), - widget=SelectDateTime, required=True) - start_candidature = forms.DateTimeField( - ['%Y-%m-%d %H:%M:%S'], label=_("Start candidature"), - widget=SelectDateTime, required=True) - end_candidature = forms.DateTimeField( - ['%Y-%m-%d %H:%M:%S'], label=_("End candidature"), - widget=SelectDateTime, required=True) + start_date = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("Start date"), + widget=SelectDateTime, required=True) + end_date = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("End date"), + widget=SelectDateTime, required=True) + start_candidature = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("Start candidature"), + widget=SelectDateTime, required=True) + end_candidature = forms.DateTimeField(['%Y-%m-%d %H:%M:%S'], label=_("End candidature"), + widget=SelectDateTime, required=True) # Display elections @@ -169,8 +157,7 @@ class ElectionsListView(CanViewMixin, ListView): template_name = 'election/election_list.jinja' def get_queryset(self): - return super(ElectionsListView, - self).get_queryset().filter(archived=False).all() + return super(ElectionsListView, self).get_queryset().filter(archived=False).all() class ElectionListArchivedView(CanViewMixin, ListView): @@ -183,8 +170,7 @@ class ElectionListArchivedView(CanViewMixin, ListView): template_name = 'election/election_list.jinja' def get_queryset(self): - return super(ElectionListArchivedView, - self).get_queryset().filter(archived=True).all() + return super(ElectionListArchivedView, self).get_queryset().filter(archived=True).all() class ElectionDetailView(CanViewMixin, DetailView): @@ -222,8 +208,7 @@ class VoteFormView(CanCreateMixin, FormView): # If we have a multiple choice field if isinstance(election_data[role_title], QuerySet): if election_data[role_title].count() > 0: - vote = Vote(role=election_data[ - role_title].first().role) + vote = Vote(role=election_data[role_title].first().role) vote.save() for el in election_data[role_title]: vote.candidature.add(el) @@ -277,8 +262,7 @@ class CandidatureCreateView(CanCreateMixin, CreateView): def dispatch(self, request, *arg, **kwargs): self.election = get_object_or_404(Election, pk=kwargs['election_id']) - return super(CandidatureCreateView, - self).dispatch(request, *arg, **kwargs) + return super(CandidatureCreateView, self).dispatch(request, *arg, **kwargs) def get_initial(self): init = {} @@ -298,8 +282,7 @@ class CandidatureCreateView(CanCreateMixin, CreateView): """ obj = form.instance obj.election = Election.objects.get(id=self.election.id) - if(obj.election.can_candidate(obj.user)) and \ - (obj.user == self.request.user or self.can_edit): + if(obj.election.can_candidate(obj.user)) and (obj.user == self.request.user or self.can_edit): return super(CreateView, self).form_valid(form) raise PermissionDenied @@ -309,8 +292,7 @@ class CandidatureCreateView(CanCreateMixin, CreateView): return kwargs def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', - kwargs={'election_id': self.election.id}) + return reverse_lazy('election:detail', kwargs={'election_id': self.election.id}) class ElectionCreateView(CanCreateMixin, CreateView): @@ -321,8 +303,7 @@ class ElectionCreateView(CanCreateMixin, CreateView): def dispatch(self, request, *args, **kwargs): if not request.user.is_subscribed: raise PermissionDenied - return super(ElectionCreateView, - self).dispatch(request, *args, **kwargs) + return super(ElectionCreateView, self).dispatch(request, *args, **kwargs) def form_valid(self, form): """ @@ -332,8 +313,7 @@ class ElectionCreateView(CanCreateMixin, CreateView): return super(CreateView, self).form_valid(form) def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', - kwargs={'election_id': self.object.id}) + return reverse_lazy('election:detail', kwargs={'election_id': self.object.id}) class RoleCreateView(CanCreateMixin, CreateView): @@ -369,8 +349,7 @@ class RoleCreateView(CanCreateMixin, CreateView): return kwargs def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', - kwargs={'election_id': self.object.election.id}) + return reverse_lazy('election:detail', kwargs={'election_id': self.object.election.id}) class ElectionListCreateView(CanCreateMixin, CreateView): @@ -382,8 +361,7 @@ class ElectionListCreateView(CanCreateMixin, CreateView): self.election = get_object_or_404(Election, pk=kwargs['election_id']) if not self.election.is_vote_editable: raise PermissionDenied - return super(ElectionListCreateView, - self).dispatch(request, *arg, **kwargs) + return super(ElectionListCreateView, self).dispatch(request, *arg, **kwargs) def get_initial(self): init = {} @@ -410,8 +388,7 @@ class ElectionListCreateView(CanCreateMixin, CreateView): raise PermissionDenied def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', - kwargs={'election_id': self.object.election.id}) + return reverse_lazy('election:detail', kwargs={'election_id': self.object.election.id}) # Update view @@ -425,30 +402,25 @@ class ElectionUpdateView(CanEditMixin, UpdateView): def get_initial(self): init = {} try: - init['start_date'] = self.object.start_date.strftime( - '%Y-%m-%d %H:%M:%S') + init['start_date'] = self.object.start_date.strftime('%Y-%m-%d %H:%M:%S') except Exception: pass try: - init['end_date'] = self.object.end_date.strftime( - '%Y-%m-%d %H:%M:%S') + init['end_date'] = self.object.end_date.strftime('%Y-%m-%d %H:%M:%S') except Exception: pass try: - init['start_candidature'] = self.object.start_candidature.strftime( - '%Y-%m-%d %H:%M:%S') + init['start_candidature'] = self.object.start_candidature.strftime('%Y-%m-%d %H:%M:%S') except Exception: pass try: - init['end_candidature'] = self.object.end_candidature.strftime( - '%Y-%m-%d %H:%M:%S') + init['end_candidature'] = self.object.end_candidature.strftime('%Y-%m-%d %H:%M:%S') except Exception: pass return init def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', - kwargs={'election_id': self.object.id}) + return reverse_lazy('election:detail', kwargs={'election_id': self.object.id}) class CandidatureUpdateView(CanEditMixin, UpdateView): @@ -475,8 +447,7 @@ class CandidatureUpdateView(CanEditMixin, UpdateView): def post(self, request, *args, **kwargs): self.form = self.get_form() self.remove_fields() - if request.user.is_authenticated() and \ - request.user.can_edit(self.object) and self.form.is_valid(): + if request.user.is_authenticated() and request.user.can_edit(self.object) and self.form.is_valid(): return super(CandidatureUpdateView, self).form_valid(self.form) return self.form_invalid(self.form) @@ -486,9 +457,7 @@ class CandidatureUpdateView(CanEditMixin, UpdateView): return kwargs def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', - kwargs={'election_id': - self.object.role.election.id}) + return reverse_lazy('election:detail', kwargs={'election_id': self.object.role.election.id}) class RoleUpdateView(CanEditMixin, UpdateView): @@ -516,8 +485,7 @@ class RoleUpdateView(CanEditMixin, UpdateView): self.object = self.get_object() self.form = self.get_form() self.remove_fields() - if request.user.is_authenticated() and \ - request.user.can_edit(self.object) and self.form.is_valid(): + if request.user.is_authenticated() and request.user.can_edit(self.object) and self.form.is_valid(): return super(RoleUpdateView, self).form_valid(self.form) return self.form_invalid(self.form) @@ -527,8 +495,7 @@ class RoleUpdateView(CanEditMixin, UpdateView): return kwargs def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', - kwargs={'election_id': self.object.election.id}) + return reverse_lazy('election:detail', kwargs={'election_id': self.object.election.id}) # Delete Views @@ -540,8 +507,7 @@ class ElectionDeleteView(DeleteView): def dispatch(self, request, *args, **kwargs): if request.user.is_root: - return super(ElectionDeleteView, - self).dispatch(request, *args, **kwargs) + return super(ElectionDeleteView, self).dispatch(request, *args, **kwargs) raise PermissionDenied def get_success_url(self, **kwargs): @@ -556,15 +522,12 @@ class CandidatureDeleteView(CanEditMixin, DeleteView): def dispatch(self, request, *arg, **kwargs): self.object = self.get_object() self.election = self.object.role.election - if not self.election.can_candidate \ - or not self.election.is_vote_editable: + if not self.election.can_candidate or not self.election.is_vote_editable: raise PermissionDenied - return super(CandidatureDeleteView, - self).dispatch(request, *arg, **kwargs) + return super(CandidatureDeleteView, self).dispatch(request, *arg, **kwargs) def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', - kwargs={'election_id': self.election.id}) + return reverse_lazy('election:detail', kwargs={'election_id': self.election.id}) class RoleDeleteView(CanEditMixin, DeleteView): @@ -580,5 +543,4 @@ class RoleDeleteView(CanEditMixin, DeleteView): return super(RoleDeleteView, self).dispatch(request, *arg, **kwargs) def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', - kwargs={'election_id': self.election.id}) + return reverse_lazy('election:detail', kwargs={'election_id': self.election.id}) From ea09604b2e217649d8736c07e3bc3c8fe38b3d9f Mon Sep 17 00:00:00 2001 From: klmp200 Date: Wed, 7 Jun 2017 19:27:18 +0200 Subject: [PATCH 6/6] Other line fix --- election/views.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/election/views.py b/election/views.py index 7fd9907d..6f8b5f8c 100644 --- a/election/views.py +++ b/election/views.py @@ -29,10 +29,9 @@ class LimitedCheckboxField(forms.ModelMultipleChoiceField): label=None, initial=None, help_text='', *args, **kwargs): self.max_choice = max_choice widget = forms.CheckboxSelectMultiple() - super(LimitedCheckboxField, self).__init__(queryset, None, required, - widget, label, - initial, help_text, - *args, **kwargs) + super(LimitedCheckboxField, + self).__init__(queryset, None, required, widget, + label, initial, help_text, *args, **kwargs) def clean(self, value): qs = super(LimitedCheckboxField, self).clean(value) @@ -56,8 +55,7 @@ class CandidateForm(forms.ModelForm): 'program': forms.Textarea } - user = AutoCompleteSelectField('users', label=_( - 'User to candidate'), help_text=None, required=True) + user = AutoCompleteSelectField('users', label=_('User to candidate'), help_text=None, required=True) def __init__(self, *args, **kwargs): election_id = kwargs.pop('election_id', None) @@ -94,16 +92,14 @@ class RoleForm(forms.ModelForm): election_id = kwargs.pop('election_id', None) super(RoleForm, self).__init__(*args, **kwargs) if election_id: - self.fields['election'].queryset = Election.objects.filter( - id=election_id).all() + self.fields['election'].queryset = Election.objects.filter(id=election_id).all() def clean(self): cleaned_data = super(RoleForm, self).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') + raise forms.ValidationError(_("This role already exists for this election"), code='invalid') class ElectionListForm(forms.ModelForm): @@ -238,8 +234,7 @@ class VoteFormView(CanCreateMixin, FormView): return res def get_success_url(self, **kwargs): - return reverse_lazy('election:detail', - kwargs={'election_id': self.election.id}) + return reverse_lazy('election:detail', kwargs={'election_id': self.election.id}) def get_context_data(self, **kwargs): """ Add additionnal data to the template """ @@ -433,8 +428,7 @@ class CandidatureUpdateView(CanEditMixin, UpdateView): self.object = self.get_object() if not self.object.role.election.is_vote_editable: raise PermissionDenied - return super(CandidatureUpdateView, - self).dispatch(request, *arg, **kwargs) + return super(CandidatureUpdateView, self).dispatch(request, *arg, **kwargs) def remove_fields(self): self.form.fields.pop('role', None)