OpenSlides/openslides/poll/models.py

243 lines
6.5 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
openslides.poll.models
~~~~~~~~~~~~~~~~~~~~~~
Models for the poll app.
:copyright: 2011, 2012 by OpenSlides team, see AUTHORS.
:license: GNU GPL, see LICENSE for more details.
"""
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.utils.translation import ugettext_lazy as _, ugettext_noop
from openslides.utils.modelfields import MinMaxIntegerField
class BaseOption(models.Model):
"""
Base option class for a Poll.
Subclasses have to define a poll-field, which are a subclass of BasePoll.
"""
def get_votes(self):
return self.get_vote_class().objects.filter(option=self)
def __getitem__(self, name):
try:
return self.get_votes().get(value=name)
except self.get_vote_class().DoesNotExist:
return None
def get_vote_class(self):
return self.vote_class
class Meta:
abstract = True
class BaseVote(models.Model):
"""
Base Vote class for an option.
Subclasses have to define a option-field, which are a subclass of
BaseOption.
"""
weight = models.IntegerField(default=1, null=True) # Use MinMaxIntegerField
value = models.CharField(max_length=255, null=True)
def print_weight(self, raw=False):
if raw:
return self.weight
try:
percent_base = self.option.poll.percent_base()
except AttributeError:
# The poll class is no child of CountVotesCast
percent_base = 0
return print_value(self.weight, percent_base)
def get_value(self):
return _(self.value)
def __unicode__(self):
return self.print_weight()
class Meta:
abstract = True
class CountVotesCast(models.Model):
votescast = MinMaxIntegerField(null=True, blank=True, min_value=-2,
verbose_name=_("Votes cast"))
def append_pollform_fields(self, fields):
fields.append('votescast')
def print_votescast(self):
return print_value(self.votescast)
def percent_base(self):
if self.votescast > 0:
return 100 / float(self.votescast)
return 0
class Meta:
abstract = True
class CountInvalid(models.Model):
votesinvalid = MinMaxIntegerField(null=True, blank=True, min_value=-2,
verbose_name=_("Votes invalid"))
def append_pollform_fields(self, fields):
fields.append('votesinvalid')
def print_votesinvalid(self):
try:
percent_base = self.percent_base()
except AttributeError:
# The poll class is no child of CountVotesCast
percent_base = 0
return print_value(self.votesinvalid, percent_base)
class Meta:
abstract = True
class PublishPollMixin(models.Model):
published = models.BooleanField(default=False)
def set_published(self, published):
self.published = published
self.save()
class Meta:
abstract = True
class BasePoll(models.Model):
"""
Base poll class.
"""
vote_values = [ugettext_noop('votes')]
def has_votes(self):
"""
Return True, the there are votes in the poll.
"""
if self.get_votes().exists():
return True
return False
def set_options(self, options_data=[]):
"""
Add new Option pbjects to the poll.
option_data: A List of arguments for the Option.
"""
for option_data in options_data:
option = self.get_option_class()(**option_data)
option.poll = self
option.save()
def get_options(self):
"""
Return the option objects for the poll.
"""
return self.get_option_class().objects.filter(poll=self)
def get_option_class(self):
"""
Return the option class for the poll. Default is self.option_class.
"""
return self.option_class
def get_vote_values(self):
"""
Return the possible values for the poll as list.
"""
return self.vote_values
def get_vote_class(self):
"""
Return the releatet vote class.
"""
return self.get_option_class().vote_class
def get_votes(self):
"""
Return a QuerySet with all vote objects, releatet to this poll.
"""
return self.get_vote_class().objects.filter(option__poll__id=self.id)
def set_form_values(self, option, data):
# TODO: recall this function. It has nothing to do with a form
"""
Create or update the vote objects for the poll.
"""
for value in self.get_vote_values():
try:
vote = self.get_votes().filter(option=option).get(value=value)
except ObjectDoesNotExist:
vote = self.get_vote_class()(option=option, value=value)
vote.weight = data[value]
vote.save()
def get_form_values(self, option_id):
# TODO: recall this function. It has nothing to do with a form
"""
Return a the values and the weight of the values as a list with two
elements.
"""
values = []
for value in self.get_vote_values():
try:
vote = self.get_votes().filter(option=option_id) \
.get(value=value)
values.append(vote)
except ObjectDoesNotExist:
values.append(self.get_vote_class()(value=value, weight=''))
return values
def get_vote_form(self, **kwargs):
"""
Return the form for one option of the poll.
"""
from openslides.poll.forms import OptionForm
return OptionForm(extra=self.get_form_values(kwargs['formid']),
**kwargs)
def get_vote_forms(self, **kwargs):
"""
Return a list of forms for the poll
"""
forms = []
for option in self.get_options():
form = self.get_vote_form(formid=option.id, **kwargs)
form.option = option
forms.append(form)
return forms
class Meta:
abstract = True
def print_value(value, percent_base=0):
if value == -1:
return unicode(_('majority'))
elif value == -2:
return unicode(_('undocumented'))
elif value is None:
return unicode(_('undocumented'))
if not percent_base:
return u'%s' % value
return u'%d (%.2f %%)' % (value, value * percent_base)