Full CRUD for elections

This commit is contained in:
Antoine Bartuccio 2016-12-24 18:29:26 +01:00
parent 4f62863599
commit c07f49305b
7 changed files with 185 additions and 6 deletions

View File

@ -41,6 +41,10 @@ class Election(models.Model):
now = timezone.now()
return bool(now <= self.end_candidature and now >= self.start_candidature)
@property
def is_vote_editable(self):
return bool(timezone.now() <= self.end_candidature)
def can_candidate(self, user):
for group in self.candidature_groups.all():
if user.is_in_group(group):
@ -95,6 +99,10 @@ class Role(models.Model):
'percent': (total_vote - non_blank) * 100 / total_vote}
return results
@property
def edit_groups(self):
return self.election.edit_groups
def __str__(self):
return ("%s : %s") % (self.election.title, self.title)
@ -119,6 +127,9 @@ class Candidature(models.Model):
program = models.TextField(_('description'), null=True, blank=True)
election_list = models.ForeignKey(ElectionList, related_name='candidatures', verbose_name=_('election_list'))
def can_be_edited_by(self, user):
return (user == self.user)
def __str__(self):
return "%s : %s" % (self.role.title, self.user.username)

View File

@ -0,0 +1,15 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Create{% endtrans %}
{% endblock %}
{% block content %}
<h2>{% trans %}Create{% endtrans %}
<section class="election__add-candidature">
<form action="" method="post">{{form.as_p()}}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
{% csrf_token %}
</form>
</section>
{% endblock content %}

View File

@ -0,0 +1,12 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Delete{% endtrans %}
{% endblock %}
{% block content %}
<form action="" method="post">{% csrf_token %}
<p>{% trans %}Are you sure you want to delete {% endtrans %}"{{ object }}"?</p>
<input type="submit" value="Confirm" />
</form>
{% endblock content %}

View File

@ -273,6 +273,10 @@ th {
<tr class="role__title">
<td colspan="{{election_lists.count() + 1}}">
<span>{{role.title}}</span>
{% if user.can_edit(role) and election.is_vote_editable -%}
<a href="{{url('election:update_role', role_id=role.id)}}">{% trans %}Edit{% endtrans %}</a>
<a href="{{url('election:delete_role', role_id=role.id)}}">{% trans %}Delete{% endtrans %}</a>
{%- endif -%}
{%- if role.max_choice > 1 and not election.has_voted(user) and election.can_vote(user) %}
<strong class="role__multiple-choices-label">{% trans %}You may choose up to{% endtrans %} {{ role.max_choice }} {% trans %}people.{% endtrans %}</strong>
{%- endif %}
@ -313,6 +317,14 @@ th {
<figcaption class="candidate__details">
<cite class="candidate__full-name">{{ candidature.user.first_name }} <em class="candidate__nick-name">{{candidature.user.nick_name or ''}} </em>{{ candidature.user.last_name }}</cite>
<q class="candidate__program">{{ candidature.program or '' }}</q>
{%- if user.can_edit(candidature) -%}
{% if election.is_vote_editable %}
<a href="{{url('election:update_candidate', candidature_id=candidature.id)}}">{% trans %}Edit{% endtrans %}</a>
{% endif %}
{% if election.can_candidate -%}
<a href="{{url('election:delete_candidate', candidature_id=candidature.id)}}">{% trans %}Delete{% endtrans %}</a>
{%- endif -%}
{%- endif -%}
</figcaption>
</figure>
{%- if election.can_vote(user) %}

View File

@ -0,0 +1,15 @@
{% extends "core/base.jinja" %}
{% block title %}
{% trans %}Edit{% endtrans %}
{% endblock %}
{% block content %}
<h2>{% trans %}Edit{% endtrans %}
<section class="election__add-candidature">
<form action="" method="post">{{form.as_p()}}
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
{% csrf_token %}
</form>
</section>
{% endblock content %}

View File

@ -8,7 +8,11 @@ urlpatterns = [
url(r'^(?P<election_id>[0-9]+)/edit$', ElectionUpdateView.as_view(), name='update'),
url(r'^(?P<election_id>[0-9]+)/list/add$', ElectionListCreateView.as_view(), name='create_list'),
url(r'^(?P<election_id>[0-9]+)/role/create$', RoleCreateView.as_view(), name='create_role'),
url(r'^(?P<role_id>[0-9]+)/role/edit$', RoleUpdateView.as_view(), name='update_role'),
url(r'^(?P<role_id>[0-9]+)/role/delete$', RoleDeleteView.as_view(), name='delete_role'),
url(r'^(?P<election_id>[0-9]+)/candidate/add$', CandidatureCreateView.as_view(), name='candidate'),
url(r'^(?P<candidature_id>[0-9]+)/candidate/edit$', CandidatureUpdateView.as_view(), name='update_candidate'),
url(r'^(?P<candidature_id>[0-9]+)/candidate/delete$', CandidatureDeleteView.as_view(), name='delete_candidate'),
url(r'^(?P<election_id>[0-9]+)/vote$', VoteFormView.as_view(), name='vote'),
url(r'^(?P<election_id>[0-9]+)/detail$', ElectionDetailView.as_view(), name='detail'),
]

View File

@ -265,7 +265,7 @@ class CandidatureCreateView(CanCreateMixin, CreateView):
class ElectionCreateView(CanCreateMixin, CreateView):
model = Election
form_class = ElectionForm
template_name = 'core/page_prop.jinja'
template_name = 'election/create_template.jinja'
def dispatch(self, request, *args, **kwargs):
if not request.user.is_subscribed():
@ -285,11 +285,11 @@ class ElectionCreateView(CanCreateMixin, CreateView):
class RoleCreateView(CanCreateMixin, CreateView):
model = Role
form_class = RoleForm
template_name = 'core/page_prop.jinja'
template_name = 'election/create_template.jinja'
def dispatch(self, request, *arg, **kwargs):
self.election = get_object_or_404(Election, pk=kwargs['election_id'])
if self.election.is_vote_active or self.election.is_vote_finished:
if self.election.is_vote_editable:
raise PermissionDenied
return super(RoleCreateView, self).dispatch(request, *arg, **kwargs)
@ -321,11 +321,11 @@ class RoleCreateView(CanCreateMixin, CreateView):
class ElectionListCreateView(CanCreateMixin, CreateView):
model = ElectionList
form_class = ElectionListForm
template_name = 'core/page_prop.jinja'
template_name = 'election/create_template.jinja'
def dispatch(self, request, *arg, **kwargs):
self.election = get_object_or_404(Election, pk=kwargs['election_id'])
if self.election.is_vote_finished:
if not self.election.is_vote_editable:
raise PermissionDenied
return super(ElectionListCreateView, self).dispatch(request, *arg, **kwargs)
@ -362,6 +362,116 @@ class ElectionListCreateView(CanCreateMixin, CreateView):
class ElectionUpdateView(CanEditMixin, UpdateView):
model = Election
form_class = ElectionForm
template_name = 'core/page_prop.jinja'
template_name = 'election/update_template.jinja'
pk_url_kwarg = 'election_id'
def get_success_url(self, **kwargs):
return reverse_lazy('election:detail', kwargs={'election_id': self.object.id})
class CandidatureUpdateView(CanEditMixin, UpdateView):
model = Candidature
form_class = CandidateForm
template_name = 'election/update_template.jinja'
pk_url_kwarg = 'candidature_id'
def dispatch(self, request, *arg, **kwargs):
self.object = self.get_object()
if not self.object.role.election.is_vote_editable:
raise PermissionDenied
return super(CandidatureUpdateView, self).dispatch(request, *arg, **kwargs)
def remove_fields(self):
self.form.fields.pop('role', None)
def get(self, request, *args, **kwargs):
self.form = self.get_form()
self.remove_fields()
return self.render_to_response(self.get_context_data(form=self.form))
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():
return super(CandidatureUpdateView, self).form_valid(self.form)
return self.form_invalid(self.form)
def get_form_kwargs(self):
kwargs = super(CandidatureUpdateView, self).get_form_kwargs()
kwargs['election_id'] = self.object.role.election.id
return kwargs
def get_success_url(self, **kwargs):
return reverse_lazy('election:detail', kwargs={'election_id': self.object.role.election.id})
class RoleUpdateView(CanEditMixin, UpdateView):
model = Role
form_class = RoleForm
template_name = 'election/update_template.jinja'
pk_url_kwarg = 'role_id'
def dispatch(self, request, *arg, **kwargs):
self.object = self.get_object()
if not self.object.election.is_vote_editable:
raise PermissionDenied
return super(RoleUpdateView, self).dispatch(request, *arg, **kwargs)
def remove_fields(self):
self.form.fields.pop('election', None)
def get(self, request, *args, **kwargs):
self.object = self.get_object()
self.form = self.get_form()
self.remove_fields()
return self.render_to_response(self.get_context_data(form=self.form))
def post(self, request, *args, **kwargs):
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():
return super(RoleUpdateView, self).form_valid(self.form)
return self.form_invalid(self.form)
def get_form_kwargs(self):
kwargs = super(RoleUpdateView, self).get_form_kwargs()
kwargs['election_id'] = self.object.election.id
return kwargs
def get_success_url(self, **kwargs):
return reverse_lazy('election:detail', kwargs={'election_id': self.object.election.id})
# Delete Views
class CandidatureDeleteView(CanEditMixin, DeleteView):
model = Candidature
template_name = 'election/delete_template.jinja'
pk_url_kwarg = 'candidature_id'
def dispatch(self, request, *arg, **kwargs):
self.object = self.get_object()
self.election = self.object.role.election
if not self.election.can_candidate:
raise PermissionDenied
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})
class RoleDeleteView(CanEditMixin, DeleteView):
model = Role
template_name = 'election/delete_template.jinja'
pk_url_kwarg = 'role_id'
def dispatch(self, request, *arg, **kwargs):
self.object = self.get_object()
self.election = self.object.election
if not self.election.is_vote_editable:
raise PermissionDenied
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})