Sith/election/views.py

263 lines
9.3 KiB
Python

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.utils.translation import ugettext_lazy as _
from django.forms.models import modelform_factory
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist, ImproperlyConfigured
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 django.views.generic.edit import FormMixin
from core.views.forms import SelectDateTime
from election.models import Election, Role, Candidature, ElectionList
from ajax_select.fields import AutoCompleteSelectField
# Custom form field
class VoteCheckbox(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):
self.max_choice = max_choice
widget = forms.CheckboxSelectMultiple
super(VoteCheckbox, self).__init__(queryset, None, required, widget, label,
initial, help_text, *args, **kwargs)
def clean(self, value):
qs = super(VoteCheckbox, self).clean(value)
self.validate(qs)
def validate(self, qs):
if qs.count() > self.max_choice:
raise forms.ValidationError(_("You have selected too much candidate"))
# Forms
class CandidateForm(forms.Form):
""" Form to candidate """
user = AutoCompleteSelectField('users', label=_('User to candidate'), help_text=None, required=True)
program = forms.CharField(widget=forms.Textarea)
def __init__(self, election_id, *args, **kwargs):
super(CandidateForm, self).__init__(*args, **kwargs)
self.fields['role'] = forms.ModelChoiceField(Role.objects.filter(election__id=election_id))
self.fields['election_list'] = forms.ModelChoiceField(ElectionList.objects.filter(election__id=election_id))
class VoteForm(forms.Form):
def __init__(self, election, user, *args, **kwargs):
super(VoteForm, self).__init__(*args, **kwargs)
for role in election.role.all():
if not role.user_has_voted(user):
cand = role.candidature
if role.max_choice > 1:
self.fields[role.title] = VoteCheckbox(cand, role.max_choice, required=False)
else:
self.fields[role.title] = forms.ModelChoiceField(cand, required=False,
widget=forms.RadioSelect(), empty_label=_("Blank vote"))
# Display elections
class ElectionsListView(CanViewMixin, ListView):
"""
A list with all responsabilities and their candidates
"""
model = Election
template_name = 'election/election_list.jinja'
def get_queryset(self):
qs = super(ElectionsListView, self).get_queryset()
today = timezone.now()
qs = qs.filter(end_date__gte=today, start_date__lte=today)
return qs
class ElectionDetailView(CanViewMixin, DetailView):
"""
Details an election responsability by responsability
"""
model = Election
template_name = 'election/election_detail.jinja'
pk_url_kwarg = "election_id"
def get_context_data(self, **kwargs):
""" Add additionnal data to the template """
kwargs = super(ElectionDetailView, self).get_context_data(**kwargs)
kwargs['candidate_form'] = CandidateForm(self.get_object().id)
kwargs['election_form'] = VoteForm(self.get_object(), self.request.user)
return kwargs
# Form view
class CandidatureCreateView(CanCreateMixin, FormView):
"""
View dedicated to a cundidature creation
"""
form_class = CandidateForm
template_name = 'core/page_prop.jinja'
def dispatch(self, request, *arg, **kwargs):
self.election_id = kwargs['election_id']
return super(CandidatureCreateView, self).dispatch(request, *arg, **kwargs)
def get_form_kwargs(self):
kwargs = super(CandidatureCreateView, self).get_form_kwargs()
kwargs['election_id'] = self.election_id
return kwargs
def create_candidature(self, data):
cand = Candidature(
role=data['role'],
user=data['user'],
election_list=data['election_list'],
program=data['program']
)
cand.save()
def form_valid(self, form):
"""
Verify that the selected user is in candidate group
"""
data = form.clean()
res = super(FormView, self).form_valid(form)
data['election'] = Election.objects.get(id=self.election_id)
for grp in data['election'].candidature_groups.all():
if data['user'].is_in_group(grp):
self.create_candidature(data)
return res
return res
def get_success_url(self, **kwargs):
return reverse_lazy('election:detail', kwargs={'election_id': self.election_id})
class VoteFormView(CanCreateMixin, FormView):
"""
Alows users to vote
"""
form_class = VoteForm
template_name = 'election/election_detail.jinja'
def dispatch(self, request, *arg, **kwargs):
self.election = get_object_or_404(Election, pk=kwargs['election_id'])
return super(VoteFormView, self).dispatch(request, *arg, **kwargs)
def vote(self, data):
print(data)
def get_form_kwargs(self):
kwargs = super(VoteFormView, self).get_form_kwargs()
kwargs['election'] = self.election
kwargs['user'] = self.request.user
return kwargs
def form_valid(self, form):
"""
Verify that the user is part in a vote group
"""
data = form.clean()
res = super(FormView, self).form_valid(form)
for grp in self.election.vote_groups.all():
if self.request.user.is_in_group(grp):
self.vote(data)
return res
return res
def get_success_url(self, **kwargs):
return reverse_lazy('election:detail', kwargs={'election_id': self.election.id})
def get_context_data(self, **kwargs):
""" Add additionnal data to the template """
kwargs = super(VoteFormView, self).get_context_data(**kwargs)
kwargs['candidate_form'] = CandidateForm(self.election.id)
kwargs['object'] = self.election
kwargs['election'] = self.election
kwargs['election_form'] = self.get_form()
return kwargs
# Create views
class ElectionCreateView(CanCreateMixin, CreateView):
model = Election
form_class = modelform_factory(Election,
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,
'edit_groups': CheckboxSelectMultiple,
'vote_groups': CheckboxSelectMultiple,
'candidature_groups': CheckboxSelectMultiple,
'start_date': SelectDateTime,
'end_date': SelectDateTime,
'start_candidature': SelectDateTime,
'end_candidature': SelectDateTime,
})
template_name = 'core/page_prop.jinja'
def get_success_url(self, **kwargs):
return reverse_lazy('election:detail', kwargs={'election_id': self.object.id})
class RoleCreateView(CanCreateMixin, CreateView):
model = Role
form_class = modelform_factory(Role,
fields=['title', 'election', 'title', 'description', 'max_choice'])
template_name = 'core/page_prop.jinja'
def form_valid(self, form):
"""
Verify that the user can edit proprely
"""
obj = form.instance
res = super(CreateView, self).form_valid
if obj.election:
for grp in obj.election.edit_groups.all():
if self.request.user.is_in_group(grp):
return res(form)
raise PermissionDenied
def get_success_url(self, **kwargs):
return reverse_lazy('election:detail', kwargs={'election_id': self.object.election.id})
class ElectionListCreateView(CanCreateMixin, CreateView):
model = ElectionList
form_class = modelform_factory(ElectionList,
fields=['title', 'election'])
template_name = 'core/page_prop.jinja'
def form_valid(self, form):
"""
Verify that the user can vote on this election
"""
obj = form.instance
res = super(CreateView, self).form_valid
if obj.election:
for grp in obj.election.candidature_groups.all():
if self.request.user.is_in_group(grp):
return res(form)
for grp in obj.election.edit_groups.all():
if self.request.user.is_in_group(grp):
return res(form)
raise PermissionDenied
def get_success_url(self, **kwargs):
return reverse_lazy('election:detail', kwargs={'election_id': self.object.election.id})