diff --git a/pylab/core/migrations/0009_votingpoll_projects.py b/pylab/core/migrations/0009_votingpoll_projects.py new file mode 100644 index 0000000..b7ab089 --- /dev/null +++ b/pylab/core/migrations/0009_votingpoll_projects.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0008_auto_20150809_0654'), + ] + + operations = [ + migrations.AddField( + model_name='votingpoll', + name='projects', + field=models.ManyToManyField(to='core.Project'), + ), + ] diff --git a/pylab/core/migrations/0013_merge.py b/pylab/core/migrations/0013_merge.py new file mode 100644 index 0000000..cc7276d --- /dev/null +++ b/pylab/core/migrations/0013_merge.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0009_votingpoll_projects'), + ('core', '0012_merge'), + ] + + operations = [ + ] diff --git a/pylab/core/models.py b/pylab/core/models.py index 0e82cfa..f46d09e 100644 --- a/pylab/core/models.py +++ b/pylab/core/models.py @@ -80,10 +80,17 @@ class VotingPoll(models.Model): slug = AutoSlugField(populate_from='title') title = models.CharField(_("Title"), max_length=255) description = models.TextField(_("Description"), blank=True) + projects = models.ManyToManyField(Project) def __str__(self): return self.title + def get_absolute_url(self): + return reverse('voting-poll-details', args=[self.slug]) + + def get_voting_url(self): + return reverse('voting-page', args=[self.slug]) + class Vote(models.Model): created = CreationDateTimeField() diff --git a/pylab/website/forms.py b/pylab/website/forms.py index 5a16c39..ea5d64c 100644 --- a/pylab/website/forms.py +++ b/pylab/website/forms.py @@ -55,16 +55,34 @@ def clean(self): self.check_existing_events(title, starts) -class VotePointsForm(forms.ModelForm): +class ProjectPointsForm(forms.ModelForm): + points = forms.IntegerField( + min_value=0, + widget=forms.NumberInput(attrs={'max': 99, 'min': 0, 'class': 'vote-points-input'}), + ) + + def __init__(self, user, voting_poll, *args, **kwargs): + self.user = user + self.voting_poll = voting_poll + super(ProjectPointsForm, self).__init__(*args, **kwargs) + + try: + vote = Vote.objects.get(voter=self.user, project__id=self.initial['id']) + self.fields['points'].initial = vote.points + except Vote.DoesNotExist: + pass + class Meta: - model = Vote - fields = ('points',) - widgets = { - 'points': forms.NumberInput(attrs={'max': 99, 'class': 'vote-points-input'}), - } + model = Project + fields = tuple() - def save(self, commit=True, *args, **kwargs): - vote = super(VotePointsForm, self).save(commit=False, *args, **kwargs) + def save(self, commit=True, *args, **kwargs): # pylint: disable=unused-argument + vote, created = Vote.objects.get_or_create( # pylint: disable=unused-variable + voter=self.user, + project=self.instance, + voting_poll=self.voting_poll + ) + vote.points = self.cleaned_data['points'] vote.voted = datetime.datetime.now() vote.save() @@ -75,7 +93,7 @@ def clean(self, *args, **kwargs): total_points = 0 for form in self.forms: - if form.cleaned_data['points']: + if form.cleaned_data.get('points'): total_points += form.cleaned_data['points'] if total_points < 0 or total_points > 15: diff --git a/pylab/website/static/css/main.scss b/pylab/website/static/css/main.scss index 0a74607..f67f1aa 100644 --- a/pylab/website/static/css/main.scss +++ b/pylab/website/static/css/main.scss @@ -52,7 +52,7 @@ } .vote-points-input { - width: 38px; + width: 42px; text-align: right; font-weight: bold; } diff --git a/pylab/website/templates/website/voting_page.html b/pylab/website/templates/website/voting_page.html index 2967c91..22246de 100644 --- a/pylab/website/templates/website/voting_page.html +++ b/pylab/website/templates/website/voting_page.html @@ -20,7 +20,6 @@

{{ voting_poll.title }}

{{ formset.management_form }} {% for form in formset %}
- {{ form.errors }}

{% for hidden in form.hidden_fields %} {{ hidden }} @@ -28,7 +27,7 @@

{{ voting_poll.title }}

{% for field in form.visible_fields %}
{{ field.errors }} - {{ field }} {{ form.instance.project.title }} + {{ field }} {{ form.instance.title }}
{% endfor %}

diff --git a/pylab/website/tests/test_voting.py b/pylab/website/tests/test_voting.py index 1037267..66fd7aa 100644 --- a/pylab/website/tests/test_voting.py +++ b/pylab/website/tests/test_voting.py @@ -35,9 +35,9 @@ def test_voting_page(self): time_after_vote = datetime.datetime.now() - self.assertEqual(list(Vote.objects.values_list('points', flat=True)), [3, 2]) + self.assertEqual(list(Vote.objects.filter(voter=self.u1).values_list('points', flat=True)), [3, 2]) - for v in Vote.objects.all(): + for v in Vote.objects.filter(voter=self.u1): self.assertLess(time_before_vote, v.voted) self.assertGreater(time_after_vote, v.voted) @@ -46,8 +46,8 @@ def test_voting_page(self): time_before_vote = datetime.datetime.now() - resp.form['form-0-points'].value = 30 # Vote points sum should be less or equal to 15 - resp.form['form-1-points'].value = 20 + resp.form['form-0-points'].value = 6 # Vote points sum should be less or equal to 15 + resp.form['form-1-points'].value = 5 resp = resp.form.submit() self.assertEqual(resp.status_int, 200) diff --git a/pylab/website/views.py b/pylab/website/views.py index a3bba15..af7fb98 100644 --- a/pylab/website/views.py +++ b/pylab/website/views.py @@ -1,3 +1,5 @@ +from django.utils.functional import curry + from django.contrib import messages from django.contrib.auth.decorators import login_required from django.forms.models import modelformset_factory @@ -7,7 +9,7 @@ from django.utils.translation import ugettext from django.db.models import Sum -from pylab.core.models import Project, Event, Attendance, Vote, VotingPoll +from pylab.core.models import Project, Event, Attendance, VotingPoll from pylab.website.helpers import formrenderer from pylab.website.helpers.decorators import superuser_required from pylab.website.services import weeklyevents @@ -133,22 +135,25 @@ def create_weekly_event(request, year, month, day, slug): def voting_page(request, voting_poll_slug): voting_poll = get_object_or_404(VotingPoll, slug=voting_poll_slug) total_points = 15 - VotePointsFormSet = modelformset_factory( - Vote, - form=website_forms.VotePointsForm, + ProjectPointsFormSet = modelformset_factory( + Project, + form=website_forms.ProjectPointsForm, formset=website_forms.BaseTotalPointsFormset, extra=0, ) - vote_qs = Vote.objects.filter(voter=request.user, voting_poll__slug=voting_poll_slug) + ProjectPointsFormSet.form = staticmethod(curry( + website_forms.ProjectPointsForm, + user=request.user, + voting_poll=voting_poll)) if request.method == 'POST': - formset = VotePointsFormSet(request.POST, queryset=vote_qs) + formset = ProjectPointsFormSet(request.POST, queryset=voting_poll.projects.all()) if formset.is_valid(): formset.save() messages.success(request, ugettext("Vote for ā€ž%sā€œ voting poll was saved successfully." % voting_poll)) - return redirect('project-list') + return redirect(voting_poll) else: - formset = VotePointsFormSet(queryset=vote_qs) + formset = ProjectPointsFormSet(queryset=voting_poll.projects.all()) return render(request, 'website/voting_page.html', { 'voting_poll': voting_poll,