use the new poll-api in assignments

This commit is contained in:
Oskar Hahn 2012-02-19 19:27:00 +01:00
parent 5aaa1a53fa
commit 70f1cb8b3e
8 changed files with 159 additions and 179 deletions

View File

@ -496,12 +496,7 @@ class ApplicationOption(BaseOption):
def __getattr__(self, name): def __getattr__(self, name):
if name in ['yes', 'no', 'contained']: if name in ['yes', 'no', 'contained']:
try: try:
value = self.get_votes().get(value=name).weight return self.get_votes().get(value=name)
if value == -1:
return _('majority')
if value == -2:
return _('undocumented')
return value
except Vote.DoesNotExist: except Vote.DoesNotExist:
pass pass
raise AttributeError(name) raise AttributeError(name)
@ -517,6 +512,7 @@ class ApplicationPoll(BasePoll, CountInvalid, CountVotesCast):
return self.application return self.application
def set_options(self): def set_options(self):
#TODO: maybe it is possible with .create() to call this without poll=self
self.get_option_class()(poll=self).save() self.get_option_class()(poll=self).save()
def append_pollform_fields(self, fields): def append_pollform_fields(self, fields):

View File

@ -79,9 +79,9 @@
<img src="/static/images/icons/voting-yes.png" title="{% trans 'Yes' %}"> {{ option.yes }}<br> <img src="/static/images/icons/voting-yes.png" title="{% trans 'Yes' %}"> {{ option.yes }}<br>
<img src="/static/images/icons/voting-no.png" title="{% trans 'No' %}"> {{ option.no }}<br> <img src="/static/images/icons/voting-no.png" title="{% trans 'No' %}"> {{ option.no }}<br>
<img src="/static/images/icons/voting-abstention.png" title="{% trans 'Abstention' %}"> {{ option.contained }}<br> <img src="/static/images/icons/voting-abstention.png" title="{% trans 'Abstention' %}"> {{ option.contained }}<br>
<img src="/static/images/icons/voting-invalid.png" title="{% trans 'Invalid' %}"> {{ poll.votesinvalid }}<br> <img src="/static/images/icons/voting-invalid.png" title="{% trans 'Invalid' %}"> {{ poll.print_votesinvalid }}<br>
<div style="border-top: 1px solid; padding-top: 5px; margin: 5px 0; width: 10em;"> <div style="border-top: 1px solid; padding-top: 5px; margin: 5px 0; width: 10em;">
<img src="/static/images/icons/voting-total.png" title="{% trans 'Votes cast' %}"> {{ poll.votescast }} <img src="/static/images/icons/voting-total.png" title="{% trans 'Votes cast' %}"> {{ poll.poll_votescast }}
</div> </div>
{% endwith %} {% endwith %}
{% if perms.application.can_manage_application %} {% if perms.application.can_manage_application %}

View File

@ -17,6 +17,7 @@ from participant.models import Profile
from projector.models import Slide from projector.models import Slide
from projector.api import register_slidemodel from projector.api import register_slidemodel
from poll.models import BasePoll, CountInvalid, CountVotesCast, BaseOption
class Assignment(models.Model, Slide): class Assignment(models.Model, Slide):
@ -73,7 +74,7 @@ class Assignment(models.Model, Slide):
@property @property
def candidates(self): def candidates(self):
return Profile.objects.filter(option__poll__assignment=self).order_by('user__first_name').distinct() return self.profile.get_query_set()
def set_elected(self, profile, value=True): def set_elected(self, profile, value=True):
if profile in self.candidates: if profile in self.candidates:
@ -88,33 +89,9 @@ class Assignment(models.Model, Slide):
return False return False
def gen_poll(self): def gen_poll(self):
from poll.models import Poll poll = AssignmentPoll(assignment=self)
poll = Poll()
candidates = list(self.profile.all())
for elected in self.elected.all():
try:
candidates.remove(elected)
except ValueError:
pass
# Option A: candidates <= available posts -> yes/no/abstention
if len(candidates) <= self.posts - self.elected.count():
poll.optiondecision = True
else:
poll.optiondecision = False
# Option B: candidates == 1 -> yes/no/abstention
#if self.profile.count() == 1:
# poll.optiondecision = True
#else:
# poll.optiondecision = False
poll.assignment = self
poll.description = self.polldescription
poll.save() poll.save()
for candidate in candidates: poll.set_options([{'candidate': profile} for profile in self.profile.all()])
poll.add_option(candidate)
return poll return poll
def slide(self): def slide(self):
@ -146,3 +123,23 @@ class Assignment(models.Model, Slide):
) )
register_slidemodel(Assignment) register_slidemodel(Assignment)
class AssignmentOption(BaseOption):
candidate = models.ForeignKey(Profile)
def __unicode__(self):
return unicode(self.candidate)
class AssignmentPoll(BasePoll, CountInvalid, CountVotesCast):
option_class = AssignmentOption
assignment = models.ForeignKey(Assignment, related_name='poll_set')
def get_assignment(self):
return self.assignment
def append_pollform_fields(self, fields):
CountInvalid.append_pollform_fields(self, fields)
CountVotesCast.append_pollform_fields(self, fields)

View File

@ -12,37 +12,32 @@
<p><b>{% trans "Short description" %}:</b> {{ poll.description }}</p> <p><b>{% trans "Short description" %}:</b> {{ poll.description }}</p>
<i>-1 := {% trans 'majority' %}, -2 := {% trans 'undocumented' %}</i> <i>-1 := {% trans 'majority' %}, -2 := {% trans 'undocumented' %}</i>
<form action="" method="post">{% csrf_token %} <form action="" method="post">{% csrf_token %}
<table class="table" style="width:auto;"> <table>
<tr> <tr>
<th>{%trans "Option" %}</th> <th>Option</th>
{% if poll.optiondecision %} {% for value in poll.get_vote_values %}
<th>{%trans "Yes" %}</th> <th>{{ value }}</th>
<th>{%trans "No" %}</th> {% endfor %}
<th>{%trans "Abstention" %}</th>
{% else %}
<th>{%trans "Votes" %}</th>
{% endif %}
</tr> </tr>
{% for option in options %} {% for form in forms %}
<tr class="{% cycle 'odd' '' %}"> <tr>
<td>{{ option }}</td> <td>{{ form.option }}</td>
{% if poll.optiondecision %} {% for value in form %}
<td>{{ option.form.yes.errors }}{{ option.form.yes }}</td> <td>
<td>{{ option.form.no.errors }}{{ option.form.no }}</td> {{ value.errors }}
<td>{{ option.form.undesided.errors }}{{ option.form.undesided }}</td> {{ value }}
{% else %} </td>
<td>{{ option.form.yes.errors }}{{ option.form.yes }}</td> {% endfor %}
{% endif %}
</tr> </tr>
{% endfor %} {% endfor %}
<tr class="total"> <tr class="total">
<td>{% trans "Invalid votes" %}</td> <td>{% trans "Invalid votes" %}</td>
<td {% if poll.optiondecision %}colspan="3"{% endif %}>{{ form.invalid.errors }}{{ form.invalid }}</td> <td>{{ pollform.votesinvalid.errors }}{{ pollform.votesinvalid }}</td>
</tr> </tr>
<tr class="total"> <tr class="total">
<td style="white-space: nowrap;"><b>{% trans "Votes cast" %}</b></td> <td>{% trans "Votes cast" %}</td>
<td {% if poll.optiondecision %}colspan="3"{% endif %}>{{ form.votescast.errors }}{{ form.votescast }}</td> <td>{{ pollform.votescast.errors }}{{ pollform.votescast }}</td>
</tr> </tr>
</table> </table>
<p> <p>

View File

@ -119,46 +119,46 @@
<p><br></p> <p><br></p>
<h3>{% trans "Election results" %}</h3> <h3>{% trans "Election results" %}</h3>
{% if assignment.poll_set.all.count > 0 %} {% if polls %}
<table id="election_table" style="width: auto;"> <table id="election_table" style="width: auto;">
<tr> <tr>
<th></th> <th></th>
{% with ballotnumber=assignment.poll_set.all.count %} {% with ballotnumber=polls.count %}
<th colspan="{{ ballotnumber|add:'1' }}" style="text-align: center;"> <th colspan="{{ ballotnumber|add:'1' }}" style="text-align: center;">
{% trans "ballot" %}</th> {% trans "ballot" %}</th>
{% endwith %} {% endwith %}
</tr> </tr>
<tr> <tr>
<th>{% trans "Candidates" %}</th> <th>{% trans "Candidates" %}</th>
{% for poll in assignment.poll_set.all %} {% for poll in polls %}
{% if poll.published and not perms.assignment.can_manage_assignment or perms.assignment.can_manage_assignment %} {# if poll.published and not perms.assignment.can_manage_assignment or perms.assignment.can_manage_assignment #}
<th style="vertical-align: top; white-space:nowrap;">{% if perms.assignment.can_manage_assignment %}<a href="{% url assignment_poll_view poll.id %}">{% endif %} <th style="vertical-align: top; white-space:nowrap;">{% if perms.assignment.can_manage_assignment %}<a href="{% url assignment_poll_view poll.id %}">{% endif %}
{{ forloop.counter }}. {% trans 'ballot' %} {{ forloop.counter }}. {% trans 'ballot' %}
{% if perms.assignment.can_manage_assignment %} {% if perms.assignment.can_manage_assignment %}
</a> </a>
{% if poll.published %} {% if poll.published %}
<a href={% url assignment_poll_notpublish poll.id %}><img <a href={% url assignment_poll_notpublish poll.id %}><img
src="/static/images/icons/user-online.png" src="/static/images/icons/user-online.png"
title="{% trans 'Unpublish results' %}"></a> title="{% trans 'Unpublish results' %}"></a>
{% else %} {% else %}
<a href={% url assignment_poll_publish poll.id %}><img <a href={% url assignment_poll_publish poll.id %}><img
src="/static/images/icons/user-offline.png" src="/static/images/icons/user-offline.png"
title="{% trans 'Publish results' %}"></a> title="{% trans 'Publish results' %}"></a>
{% endif %}
<a href="{% url assignment_poll_delete poll.id %}"><img src="/static/images/icons/edit-delete.png" title="{% trans 'Delete Poll' %}"></a>
{% endif %}
</th>
{# endif #}
{% endfor %}
{% if assignment.profile.count > 0 and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
<th>
<a href='{% url assignment_gen_poll assignment.id %}'>
<span class="button">
<span class="icon poll">{%trans 'New ballot' %}</span>
</span>
</a>
</th>
{% endif %} {% endif %}
<a href="{% url assignment_poll_delete poll.id %}"><img src="/static/images/icons/edit-delete.png" title="{% trans 'Delete Poll' %}"></a>
{% endif %}
</th>
{% endif %}
{% endfor %}
{% if assignment.profile.count > 0 and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
<th>
<a href='{% url assignment_gen_poll assignment.id %}'>
<span class="button">
<span class="icon poll">{%trans 'New ballot' %}</span>
</span>
</a>
</th>
{% endif %}
</tr> </tr>
{% for vote in votes %} {% for vote in votes %}
@ -167,20 +167,21 @@
{% with vote|first as candidate %} {% with vote|first as candidate %}
{% if candidate.1 %} {% if candidate.1 %}
{% if perms.assignment.can_manage_assignment %} {% if perms.assignment.can_manage_assignment %}
<a class="election_link elected" href='{% url assignment_user_not_elected assignment.id candidate.0.id %}'></a> <a class="election_link elected" href='{% url assignment_user_not_elected assignment.id candidate.0.id %}'></a>
{% else %} {% else %}
<a class="elected"><img src="/static/images/icons/games-highscores.png" title="{% trans 'Candidate is elected' %}"></a> <a class="elected"><img src="/static/images/icons/games-highscores.png" title="{% trans 'Candidate is elected' %}"></a>
{% endif %} {% endif %}
{% else %} {% else %}
{% if perms.assignment.can_manage_assignment %} {% if perms.assignment.can_manage_assignment %}
<a class="election_link" href='{% url assignment_user_elected assignment.id candidate.0.id %}'></a> <a class="election_link" href='{% url assignment_user_elected assignment.id candidate.0.id %}'></a>
{% endif %} {% endif %}
{% endif %} {% endif %}
{{ candidate.0 }} {{ candidate.0 }}
{% endwith %} {% endwith %}
</td> </td>
{% for v in vote|last %} {% for v in vote|last %}
<td style="white-space:nowrap;">{% if v %} <td style="white-space:nowrap;">
{% if v %}
{% if v|length == 3 %} {% if v|length == 3 %}
<img src="/static/images/icons/voting-yes.png" title="{% trans 'Yes' %}"> {% if v.0 %}{{ v.0 }}{% else %}&empty;{% endif %}<br> <img src="/static/images/icons/voting-yes.png" title="{% trans 'Yes' %}"> {% if v.0 %}{{ v.0 }}{% else %}&empty;{% endif %}<br>
<img src="/static/images/icons/voting-no.png" title="{% trans 'No' %}"> {% if v.1 %}{{ v.1 }}{% else %}&empty;{% endif %}<br> <img src="/static/images/icons/voting-no.png" title="{% trans 'No' %}"> {% if v.1 %}{{ v.1 }}{% else %}&empty;{% endif %}<br>
@ -189,7 +190,9 @@
{% if v != "-" %}<img src="/static/images/icons/voting-yes.png" title="{% trans 'Yes' %}">{% endif %} {% if v != "-" %}<img src="/static/images/icons/voting-yes.png" title="{% trans 'Yes' %}">{% endif %}
{{ v }} {{ v }}
{% endif %} {% endif %}
{% else %}&empty;{% endif %} {% else %}
&empty;
{% endif %}
</td> </td>
{% endfor %} {% endfor %}
{% if assignment.profile.exists and perms.assignment.can_manage_assignment and assignment.status == "vot" %} {% if assignment.profile.exists and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
@ -199,9 +202,9 @@
{% endfor %} {% endfor %}
<tr> <tr>
<td>{%trans 'Invalid votes' %}</td> <td>{%trans 'Invalid votes' %}</td>
{% for p in polls %} {% for poll in polls %}
{% if p.published and not perms.assignment.can_manage_assignment or perms.assignment.can_manage_assignment %} {% if poll.published and not perms.assignment.can_manage_assignment or perms.assignment.can_manage_assignment %}
<td style="white-space:nowrap;"><img src="/static/images/icons/voting-invalid.png" title="{% trans 'Invalid' %}"> {{ p.votesinvalidf }}</td> <td style="white-space:nowrap;"><img src="/static/images/icons/voting-invalid.png" title="{% trans 'Invalid' %}"> {{ poll.print_votesinvalid }}</td>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if assignment.profile.exists and perms.assignment.can_manage_assignment and assignment.status == "vot" %} {% if assignment.profile.exists and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
@ -210,9 +213,9 @@
</tr> </tr>
<tr class="total"> <tr class="total">
<td><b>{%trans 'Votes cast' %}</b></td> <td><b>{%trans 'Votes cast' %}</b></td>
{% for p in polls %} {% for poll in polls %}
{% if p.published and not perms.assignment.can_manage_assignment or perms.assignment.can_manage_assignment %} {% if poll.published and not perms.assignment.can_manage_assignment or perms.assignment.can_manage_assignment %}
<td style="white-space:nowrap;"><img src="/static/images/icons/voting-total.png" title="{% trans 'Votes cast' %}"> <b>{{ p.votescastf }}</b></td> <td style="white-space:nowrap;"><img src="/static/images/icons/voting-total.png" title="{% trans 'Votes cast' %}"> <b>{{ poll.print_votescast }}</b></td>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if assignment.profile.exists and perms.assignment.can_manage_assignment and assignment.status == "vot" %} {% if assignment.profile.exists and perms.assignment.can_manage_assignment and assignment.status == "vot" %}

View File

@ -12,6 +12,8 @@
from django.conf.urls.defaults import * from django.conf.urls.defaults import *
from assignment.views import ViewPoll #, ActivatePoll
urlpatterns = patterns('assignment.views', urlpatterns = patterns('assignment.views',
url(r'^assignment/$', 'get_overview', \ url(r'^assignment/$', 'get_overview', \
name='assignment_overview'), name='assignment_overview'),
@ -55,8 +57,10 @@ urlpatterns = patterns('assignment.views',
url(r'^assignment/(?P<assignment_id>\d+)/gen_poll$', 'gen_poll', \ url(r'^assignment/(?P<assignment_id>\d+)/gen_poll$', 'gen_poll', \
name='assignment_gen_poll'), name='assignment_gen_poll'),
url(r'^assignment/poll/(?P<poll_id>\d+)$', 'poll_view', \ url(r'^assignment/poll/(?P<poll_id>\d+)$',
name='assignment_poll_view'), ViewPoll.as_view(),
name='assignment_poll_view'
),
url(r'^assignment/poll/(?P<poll_id>\d+)/del$', 'delete_poll', \ url(r'^assignment/poll/(?P<poll_id>\d+)/del$', 'delete_poll', \
name='assignment_poll_delete'), name='assignment_poll_delete'),

View File

@ -16,13 +16,14 @@ from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from openslides.agenda.models import Item
#from poll.models import Poll, Option
#from poll.forms import OptionResultForm, PollForm
from assignment.models import Assignment
from assignment.forms import AssignmentForm, AssignmentRunForm
from utils.utils import template, permission_required, gen_confirm_form, del_confirm_form, ajax_request from utils.utils import template, permission_required, gen_confirm_form, del_confirm_form, ajax_request
from utils.pdf import print_assignment, print_assignment_poll from utils.pdf import print_assignment, print_assignment_poll
from poll.views import PollFormView
from assignment.models import Assignment, AssignmentPoll, AssignmentOption
from assignment.forms import AssignmentForm, AssignmentRunForm
from participant.models import Profile from participant.models import Profile
@ -69,26 +70,26 @@ def view(request, assignment_id=None):
votes = [] votes = []
for candidate in assignment.candidates: for candidate in assignment.candidates:
tmplist = [[candidate, assignment.is_elected(candidate)], []] tmplist = [[candidate, assignment.is_elected(candidate)], []]
#TODO: only show published polls
for poll in assignment.poll_set.all(): for poll in assignment.poll_set.all():
if (poll.published and not request.user.has_perm('assignment.can_manage_assignment')) or request.user.has_perm('assignment.can_manage_assignment'): #if (poll.published and not request.user.has_perm('assignment.can_manage_assignment')) or request.user.has_perm('assignment.can_manage_assignment'):
if candidate in poll.options_values:
option = Option.objects.filter(poll=poll).filter(user=candidate)[0] # exisitiert der Spieler in der poll
if poll.optiondecision: if poll.get_options().filter(candidate=candidate).exists():
tmplist[1].append([option.yes, option.no, option.undesided]) option = AssignmentOption.objects.filter(poll=poll).get(candidate=candidate)
else: tmplist[1].append(option.get_votes()[0])
tmplist[1].append(option.yes) else:
else: tmplist[1].append("-")
tmplist[1].append("-")
votes.append(tmplist) votes.append(tmplist)
polls = [] polls = assignment.poll_set.all()
for poll in assignment.poll_set.filter(assignment=assignment):
polls.append(poll)
return {'assignment': assignment, return {
'form': form, 'assignment': assignment,
'votes': votes, 'form': form,
'polls': polls } 'votes': votes,
'polls': polls,
}
@permission_required('assignment.can_manage_assignment') @permission_required('assignment.can_manage_assignment')
@ -193,56 +194,26 @@ def set_active(request, assignment_id):
@permission_required('assignment.can_manage_assignment') @permission_required('assignment.can_manage_assignment')
def gen_poll(request, assignment_id): def gen_poll(request, assignment_id):
try: poll = Assignment.objects.get(pk=assignment_id).gen_poll()
poll = Assignment.objects.get(pk=assignment_id).gen_poll() messages.success(request, _("New ballot was successfully created.") )
messages.success(request, _("New ballot was successfully created.") )
except Assignment.DoesNotExist:
pass
return redirect(reverse('assignment_poll_view', args=[poll.id])) return redirect(reverse('assignment_poll_view', args=[poll.id]))
@permission_required('assignment.can_manage_assignment') class ViewPoll(PollFormView):
@template('assignment/poll_view.html') poll_class = AssignmentPoll
def poll_view(request, poll_id): template_name = 'assignment/poll_view.html'
poll = Poll.objects.get(pk=poll_id)
ballotnumber = poll.ballot def get_context_data(self, **kwargs):
options = poll.options.order_by('user__user__first_name') context = super(ViewPoll, self).get_context_data(**kwargs)
assignment = poll.assignment self.assignment = self.poll.get_assignment()
if request.user.has_perm('assignment.can_manage_assignment'): context['application'] = self.assignment
if request.method == 'POST': return context
form = PollForm(request.POST, prefix="poll")
if form.is_valid(): def get_success_url(self):
poll.votesinvalid = form.cleaned_data['invalid'] or 0 if not 'apply' in self.request.POST:
poll.votescast = form.cleaned_data['votescast'] or 0 return reverse('assignment_view', args=[self.poll.assignment.id])
poll.save() return ''
success = 0
for option in options:
option.form = OptionResultForm(request.POST, prefix="o%d" % option.id)
if option.form.is_valid():
option.voteyes = option.form.cleaned_data['yes']
option.voteno = option.form.cleaned_data['no'] or 0
option.voteundesided = option.form.cleaned_data['undesided'] or 0
option.save()
success = success + 1
if success == options.count():
messages.success(request, _("Votes are successfully saved.") )
if not 'apply' in request.POST:
return redirect(reverse('assignment_view', args=[assignment.id]))
else:
form = PollForm(initial={'invalid': poll.votesinvalid, 'votescast': poll.votescast}, prefix="poll")
for option in options:
option.form = OptionResultForm(initial={
'yes': option.voteyes,
'no': option.voteno,
'undesided': option.voteundesided,
}, prefix="o%d" % option.id)
return {
'poll': poll,
'form': form,
'options': options,
'ballotnumber': ballotnumber,
}
@permission_required('assignment.can_manage_assignment') @permission_required('assignment.can_manage_assignment')
def set_published(request, poll_id, published=True): def set_published(request, poll_id, published=True):

View File

@ -17,8 +17,6 @@ from projector.api import register_slidemodel
from projector.models import Slide from projector.models import Slide
class BaseOption(models.Model): class BaseOption(models.Model):
poll = models.ForeignKey('BasePoll') poll = models.ForeignKey('BasePoll')
@ -39,6 +37,9 @@ class Vote(models.Model):
weight = models.IntegerField(default=1) weight = models.IntegerField(default=1)
value = models.CharField(max_length=255, null=True) value = models.CharField(max_length=255, null=True)
def __unicode__(self):
return print_value(self.weight)
class CountVotesCast(models.Model): class CountVotesCast(models.Model):
votescast = models.IntegerField(null=True, blank=True, verbose_name=_("Votes cast")) votescast = models.IntegerField(null=True, blank=True, verbose_name=_("Votes cast"))
@ -46,6 +47,9 @@ class CountVotesCast(models.Model):
def append_pollform_fields(self, fields): def append_pollform_fields(self, fields):
fields.append('votescast') fields.append('votescast')
def print_votescast(self):
return print_value(self.votescast)
class Meta: class Meta:
abstract = True abstract = True
@ -56,6 +60,9 @@ class CountInvalid(models.Model):
def append_pollform_fields(self, fields): def append_pollform_fields(self, fields):
fields.append('votesinvalid') fields.append('votesinvalid')
def print_votesinvalid(self):
return print_value(self.votesinvalid)
class Meta: class Meta:
abstract = True abstract = True
@ -130,3 +137,10 @@ class BasePoll(models.Model, Slide):
register_slidemodel(BasePoll) register_slidemodel(BasePoll)
def print_value(value):
if value == -1:
return _('majority')
elif value == -2:
return _('undocumented')
return unicode(value)