From c07f49305b9bd82524535176a864346604fd011e Mon Sep 17 00:00:00 2001 From: klmp200 Date: Sat, 24 Dec 2016 18:29:26 +0100 Subject: [PATCH] Full CRUD for elections --- election/models.py | 11 ++ .../templates/election/create_template.jinja | 15 +++ .../templates/election/delete_template.jinja | 12 ++ .../templates/election/election_detail.jinja | 12 ++ .../templates/election/update_template.jinja | 15 +++ election/urls.py | 4 + election/views.py | 122 +++++++++++++++++- 7 files changed, 185 insertions(+), 6 deletions(-) create mode 100644 election/templates/election/create_template.jinja create mode 100644 election/templates/election/delete_template.jinja create mode 100644 election/templates/election/update_template.jinja diff --git a/election/models.py b/election/models.py index 28d18e0d..097c1a58 100644 --- a/election/models.py +++ b/election/models.py @@ -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) diff --git a/election/templates/election/create_template.jinja b/election/templates/election/create_template.jinja new file mode 100644 index 00000000..3836f39b --- /dev/null +++ b/election/templates/election/create_template.jinja @@ -0,0 +1,15 @@ +{% extends "core/base.jinja" %} + +{% block title %} +{% trans %}Create{% endtrans %} +{% endblock %} + +{% block content %} +

{% trans %}Create{% endtrans %} +
+
{{form.as_p()}} +

+ {% csrf_token %} +
+
+{% endblock content %} \ No newline at end of file diff --git a/election/templates/election/delete_template.jinja b/election/templates/election/delete_template.jinja new file mode 100644 index 00000000..06ed72d4 --- /dev/null +++ b/election/templates/election/delete_template.jinja @@ -0,0 +1,12 @@ +{% extends "core/base.jinja" %} + +{% block title %} +{% trans %}Delete{% endtrans %} +{% endblock %} + +{% block content %} +
{% csrf_token %} +

{% trans %}Are you sure you want to delete {% endtrans %}"{{ object }}"?

+ +
+{% endblock content %} \ No newline at end of file diff --git a/election/templates/election/election_detail.jinja b/election/templates/election/election_detail.jinja index c1d3d5f9..f87cd971 100644 --- a/election/templates/election/election_detail.jinja +++ b/election/templates/election/election_detail.jinja @@ -273,6 +273,10 @@ th { {{role.title}} + {% if user.can_edit(role) and election.is_vote_editable -%} + {% trans %}Edit{% endtrans %} + {% trans %}Delete{% endtrans %} + {%- endif -%} {%- 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 %} @@ -313,6 +317,14 @@ th {
{{ candidature.user.first_name }} {{candidature.user.nick_name or ''}} {{ candidature.user.last_name }} {{ candidature.program or '' }} + {%- if user.can_edit(candidature) -%} + {% if election.is_vote_editable %} + {% trans %}Edit{% endtrans %} + {% endif %} + {% if election.can_candidate -%} + {% trans %}Delete{% endtrans %} + {%- endif -%} + {%- endif -%}
{%- if election.can_vote(user) %} diff --git a/election/templates/election/update_template.jinja b/election/templates/election/update_template.jinja new file mode 100644 index 00000000..604e55c4 --- /dev/null +++ b/election/templates/election/update_template.jinja @@ -0,0 +1,15 @@ +{% extends "core/base.jinja" %} + +{% block title %} +{% trans %}Edit{% endtrans %} +{% endblock %} + +{% block content %} +

{% trans %}Edit{% endtrans %} +
+
{{form.as_p()}} +

+ {% csrf_token %} +
+
+{% endblock content %} \ No newline at end of file diff --git a/election/urls.py b/election/urls.py index 75d13c02..8140cb49 100644 --- a/election/urls.py +++ b/election/urls.py @@ -8,7 +8,11 @@ urlpatterns = [ 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 ce1a0964..4dd56448 100644 --- a/election/views.py +++ b/election/views.py @@ -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})