mirror of
https://github.com/ae-utbm/sith.git
synced 2024-11-16 03:03:21 +00:00
Add new widget (not tested) and new bdd scheme for elections
This commit is contained in:
parent
7956067686
commit
d72d8366cf
@ -370,8 +370,8 @@ Cette page vise à documenter la syntaxe *Markdown* utilisée sur le site.
|
|||||||
el.save()
|
el.save()
|
||||||
el.view_groups.add(public_group)
|
el.view_groups.add(public_group)
|
||||||
el.edit_groups.add(ae_board_gorup)
|
el.edit_groups.add(ae_board_gorup)
|
||||||
el.candidature_group.add(subscriber_group)
|
el.candidature_groups.add(subscriber_group)
|
||||||
el.vote_group.add(subscriber_group)
|
el.vote_groups.add(subscriber_group)
|
||||||
el.save()
|
el.save()
|
||||||
liste = ElectionList(title="Candidature Libre", election=el)
|
liste = ElectionList(title="Candidature Libre", election=el)
|
||||||
liste.save()
|
liste.save()
|
||||||
|
94
core/widgets.py
Normal file
94
core/widgets.py
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
from django import forms
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
|
class ChoiceWithOtherRenderer(forms.RadioSelect.renderer):
|
||||||
|
"""RadioFieldRenderer that renders its last choice with a placeholder."""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(ChoiceWithOtherRenderer, self).__init__(*args, **kwargs)
|
||||||
|
self.choices, self.other = self.choices[:-1], self.choices[-1]
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
for input in super(ChoiceWithOtherRenderer, self).__iter__():
|
||||||
|
yield input
|
||||||
|
id = '%s_%s' % (self.attrs['id'], self.other[0]) if 'id' in self.attrs else ''
|
||||||
|
label_for = ' for="%s"' % id if id else ''
|
||||||
|
checked = '' if not self.other[0] == self.value else 'checked="true" '
|
||||||
|
yield '<label%s><input type="radio" id="%s" value="%s" name="%s" %s/> %s</label> %%s' % (
|
||||||
|
label_for, id, self.other[0], self.name, checked, self.other[1])
|
||||||
|
|
||||||
|
class ChoiceWithOtherWidget(forms.MultiWidget):
|
||||||
|
"""MultiWidget for use with ChoiceWithOtherField."""
|
||||||
|
def __init__(self, choices):
|
||||||
|
widgets = [
|
||||||
|
forms.RadioSelect(choices=choices, renderer=ChoiceWithOtherRenderer),
|
||||||
|
forms.TextInput
|
||||||
|
]
|
||||||
|
super(ChoiceWithOtherWidget, self).__init__(widgets)
|
||||||
|
|
||||||
|
def decompress(self, value):
|
||||||
|
if not value:
|
||||||
|
return [None, None]
|
||||||
|
return value
|
||||||
|
|
||||||
|
def format_output(self, rendered_widgets):
|
||||||
|
"""Format the output by substituting the "other" choice into the first widget."""
|
||||||
|
return rendered_widgets[0] % rendered_widgets[1]
|
||||||
|
|
||||||
|
class ChoiceWithOtherField(forms.MultiValueField):
|
||||||
|
"""
|
||||||
|
ChoiceField with an option for a user-submitted "other" value.
|
||||||
|
|
||||||
|
The last item in the choices array passed to __init__ is expected to be a choice for "other". This field's
|
||||||
|
cleaned data is a tuple consisting of the choice the user made, and the "other" field typed in if the choice
|
||||||
|
made was the last one.
|
||||||
|
|
||||||
|
>>> class AgeForm(forms.Form):
|
||||||
|
... age = ChoiceWithOtherField(choices=[
|
||||||
|
... (0, '15-29'),
|
||||||
|
... (1, '30-44'),
|
||||||
|
... (2, '45-60'),
|
||||||
|
... (3, 'Other, please specify:')
|
||||||
|
... ])
|
||||||
|
...
|
||||||
|
>>> # rendered as a RadioSelect choice field whose last choice has a text input
|
||||||
|
... print AgeForm()['age']
|
||||||
|
<ul>
|
||||||
|
<li><label for="id_age_0_0"><input type="radio" id="id_age_0_0" value="0" name="age_0" /> 15-29</label></li>
|
||||||
|
<li><label for="id_age_0_1"><input type="radio" id="id_age_0_1" value="1" name="age_0" /> 30-44</label></li>
|
||||||
|
<li><label for="id_age_0_2"><input type="radio" id="id_age_0_2" value="2" name="age_0" /> 45-60</label></li>
|
||||||
|
<li><label for="id_age_0_3"><input type="radio" id="id_age_0_3" value="3" name="age_0" /> Other, please \
|
||||||
|
specify:</label> <input type="text" name="age_1" id="id_age_1" /></li>
|
||||||
|
</ul>
|
||||||
|
>>> form = AgeForm({'age_0': 2})
|
||||||
|
>>> form.is_valid()
|
||||||
|
True
|
||||||
|
>>> form.cleaned_data
|
||||||
|
{'age': (u'2', u'')}
|
||||||
|
>>> form = AgeForm({'age_0': 3, 'age_1': 'I am 10 years old'})
|
||||||
|
>>> form.is_valid()
|
||||||
|
True
|
||||||
|
>>> form.cleaned_data
|
||||||
|
{'age': (u'3', u'I am 10 years old')}
|
||||||
|
>>> form = AgeForm({'age_0': 1, 'age_1': 'This is bogus text which is ignored since I didn\\'t pick "other"'})
|
||||||
|
>>> form.is_valid()
|
||||||
|
True
|
||||||
|
>>> form.cleaned_data
|
||||||
|
{'age': (u'1', u'')}
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
fields = [
|
||||||
|
forms.ChoiceField(widget=forms.RadioSelect(renderer=ChoiceWithOtherRenderer), *args, **kwargs),
|
||||||
|
forms.CharField(required=False)
|
||||||
|
]
|
||||||
|
widget = ChoiceWithOtherWidget(choices=kwargs['choices'])
|
||||||
|
kwargs.pop('choices')
|
||||||
|
self._was_required = kwargs.pop('required', True)
|
||||||
|
kwargs['required'] = False
|
||||||
|
super(ChoiceWithOtherField, self).__init__(widget=widget, fields=fields, *args, **kwargs)
|
||||||
|
|
||||||
|
def compress(self, value):
|
||||||
|
if self._was_required and not value or value[0] in (None, ''):
|
||||||
|
raise forms.ValidationError(self.error_messages['required'])
|
||||||
|
if not value:
|
||||||
|
return [None, u'']
|
||||||
|
return (value[0], value[1] if value[0] == self.fields[0].choices[-1][0] else u'')
|
43
election/migrations/0004_auto_20161219_2302.py
Normal file
43
election/migrations/0004_auto_20161219_2302.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0016_auto_20161212_1922'),
|
||||||
|
('election', '0003_auto_20161219_1832'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='election',
|
||||||
|
name='candidature_group',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='election',
|
||||||
|
name='vote_group',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='election',
|
||||||
|
name='candidature_groups',
|
||||||
|
field=models.ManyToManyField(to='core.Group', verbose_name='candidature group', related_name='candidate_elections', blank=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='election',
|
||||||
|
name='vote_groups',
|
||||||
|
field=models.ManyToManyField(to='core.Group', verbose_name='vote group', related_name='votable_elections', blank=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='election',
|
||||||
|
name='edit_groups',
|
||||||
|
field=models.ManyToManyField(to='core.Group', verbose_name='edit group', related_name='editable_elections', blank=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='election',
|
||||||
|
name='view_groups',
|
||||||
|
field=models.ManyToManyField(to='core.Group', verbose_name='view group', related_name='viewable_elections', blank=True),
|
||||||
|
),
|
||||||
|
]
|
@ -18,10 +18,10 @@ class Election(models.Model):
|
|||||||
start_date = models.DateTimeField(_('start date'), blank=False)
|
start_date = models.DateTimeField(_('start date'), blank=False)
|
||||||
end_date = models.DateTimeField(_('end date'), blank=False)
|
end_date = models.DateTimeField(_('end date'), blank=False)
|
||||||
|
|
||||||
edit_groups = models.ManyToManyField(Group, related_name="editable_election", verbose_name=_("edit group"), blank=True)
|
edit_groups = models.ManyToManyField(Group, related_name="editable_elections", verbose_name=_("edit group"), blank=True)
|
||||||
view_groups = models.ManyToManyField(Group, related_name="viewable_election", verbose_name=_("view group"), blank=True)
|
view_groups = models.ManyToManyField(Group, related_name="viewable_elections", verbose_name=_("view group"), blank=True)
|
||||||
vote_group = models.ManyToManyField(Group, related_name="votable_election", verbose_name=_("vote group"), blank=True)
|
vote_groups = models.ManyToManyField(Group, related_name="votable_elections", verbose_name=_("vote group"), blank=True)
|
||||||
candidature_group = models.ManyToManyField(Group, related_name="candidate_election", verbose_name=_("candidature group"), blank=True)
|
candidature_groups = models.ManyToManyField(Group, related_name="candidate_elections", verbose_name=_("candidature group"), blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
@ -11,14 +11,21 @@
|
|||||||
<h1>{{object.title}}</h1>
|
<h1>{{object.title}}</h1>
|
||||||
<p>{{object.description}}</p>
|
<p>{{object.description}}</p>
|
||||||
<p>{% trans %}End :{% endtrans %} {{object.end_date}}</p>
|
<p>{% trans %}End :{% endtrans %} {{object.end_date}}</p>
|
||||||
|
{% if object.election_list.exists() %}
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
{% set nb_list = object.election_list.all().count() + 1 -%}
|
{% set nb_list = object.election_list.all().count() + 1 -%}
|
||||||
{% for liste in object.election_list.all() %}
|
{% for liste in object.election_list.all() %}
|
||||||
<td>{{liste.title}}</td>
|
<td>{{liste.title}}</td>
|
||||||
|
{% if object.is_candidature_active -%}
|
||||||
|
{% set nb_list = nb_list -%}
|
||||||
|
{% else -%}
|
||||||
{% set nb_list = nb_list + 1 -%}
|
{% set nb_list = nb_list + 1 -%}
|
||||||
|
{% endif -%}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% if not object.is_candidature_active -%}
|
||||||
<td>{% trans %}Blank vote{% endtrans %}</td>
|
<td>{% trans %}Blank vote{% endtrans %}</td>
|
||||||
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% for role in object.role.all() %}
|
{% for role in object.role.all() %}
|
||||||
<tr><td colspan={{nb_list}}>{{role.title}}</td></tr>
|
<tr><td colspan={{nb_list}}>{{role.title}}</td></tr>
|
||||||
@ -40,8 +47,14 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% if not object.is_candidature_active -%}
|
||||||
<td></td>
|
<td></td>
|
||||||
|
{% endif %}
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
{% if object.is_candidature_active -%}
|
||||||
|
candidature
|
||||||
|
{% endif -%}
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -4,5 +4,6 @@ from election.views import *
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^$', ElectionsListView.as_view(), name='list'),
|
url(r'^$', ElectionsListView.as_view(), name='list'),
|
||||||
|
url(r'^create$', PageCreateView.as_view(), name='create'),
|
||||||
url(r'^(?P<election_id>[0-9]+)/detail$', ElectionDetailView.as_view(), name='detail'),
|
url(r'^(?P<election_id>[0-9]+)/detail$', ElectionDetailView.as_view(), name='detail'),
|
||||||
]
|
]
|
||||||
|
@ -3,12 +3,25 @@ from django.views.generic import ListView, DetailView, RedirectView
|
|||||||
from django.views.generic.edit import UpdateView, CreateView, DeleteView, FormView
|
from django.views.generic.edit import UpdateView, CreateView, DeleteView, FormView
|
||||||
from django.core.urlresolvers import reverse_lazy, reverse
|
from django.core.urlresolvers import reverse_lazy, reverse
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.forms.models import modelform_factory
|
||||||
|
from django.forms import CheckboxSelectMultiple
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django import forms
|
||||||
|
|
||||||
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin
|
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, CanCreateMixin
|
||||||
|
from core.views.forms import SelectDateTime
|
||||||
|
from core.widgets import ChoiceWithOtherField
|
||||||
from election.models import Election, Role, Candidature
|
from election.models import Election, Role, Candidature
|
||||||
|
|
||||||
|
from ajax_select.fields import AutoCompleteSelectField
|
||||||
|
|
||||||
|
# Forms
|
||||||
|
|
||||||
|
|
||||||
|
class CandidateForm(forms.Form):
|
||||||
|
user = AutoCompleteSelectField('users', label=_('Refound this account'), help_text=None, required=True)
|
||||||
|
|
||||||
# Display elections
|
# Display elections
|
||||||
|
|
||||||
|
|
||||||
@ -34,4 +47,24 @@ class ElectionDetailView(CanViewMixin, DetailView):
|
|||||||
template_name = 'election/election_detail.jinja'
|
template_name = 'election/election_detail.jinja'
|
||||||
pk_url_kwarg = "election_id"
|
pk_url_kwarg = "election_id"
|
||||||
|
|
||||||
# Forms
|
|
||||||
|
class PageCreateView(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})
|
||||||
|
Loading…
Reference in New Issue
Block a user