diff options
Diffstat (limited to 'papillon/polls/models.py')
-rw-r--r-- | papillon/polls/models.py | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/papillon/polls/models.py b/papillon/polls/models.py new file mode 100644 index 0000000..f8b3b22 --- /dev/null +++ b/papillon/polls/models.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2008 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet> + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# See the file COPYING for details. + +''' +Models management +''' + +import datetime + +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from papillon.settings import DAYS_TO_LIVE + +class Category(models.Model): + name = models.CharField(max_length=100) + description = models.TextField() + def __unicode__(self): + return self.name + +class PollUser(models.Model): + name = models.CharField(max_length=100) + email = models.CharField(max_length=100) + password = models.CharField(max_length=100) + modification_date = models.DateTimeField(auto_now=True) + +class Poll(models.Model): + base_url = models.CharField(max_length=100, help_text=_('Copy this \ +address and send it to voters who want to participate to this poll')) + admin_url = models.CharField(max_length=100, help_text=_("Address to \ +modify the current poll")) + author_name = models.CharField(verbose_name=_("Author name"), + max_length=100, help_text=_("Name, firstname or nickname of the author")) + author = models.ForeignKey(PollUser, null=True, blank=True) + name = models.CharField(max_length=200, verbose_name=_("Poll name"), + help_text=_("Global name to present the poll")) + description = models.CharField(max_length=1000, + verbose_name=_("Poll description"), + help_text=_("Precise description of the poll")) + category = models.ForeignKey(Category, null=True, blank=True) + TYPE = (('P', _('Yes/No poll')), + ('B', _('Yes/No/Maybe poll')), + ('O', _('One choice poll')), + ('V', _('Valuable choice poll')),) + type = models.CharField(max_length=1, choices=TYPE, + verbose_name=_("Type of the poll"), + help_text=_("""Type of the poll: + + - "Yes/No poll" is the appropriate type for a simple multi-choice poll + - "Yes/No/Maybe poll" allows voters to stay undecided + - "One choice poll" gives only one option to choose from + - "Valuable choice poll" permit users to give a note between 0 to 9 to \ +different choices +""")) + dated_choices = models.BooleanField(verbose_name=_("Choices are dates"), + default=False, help_text=_("Check this option to choose between dates")) + enddate = models.DateTimeField(null=True, blank=True, +verbose_name=_("Closing date"), help_text=_("Closing date for participating to \ +the poll")) + modification_date = models.DateTimeField(auto_now=True) + public = models.BooleanField(default=False, +verbose_name=_("Display the poll on main page"), help_text=_("Check this \ +option to make the poll public")) + opened_admin = models.BooleanField(default=False, +verbose_name=_("Allow users to add choices"), help_text=_("Check this option \ +to open the poll to new choices submitted by users")) + hide_choices = models.BooleanField(default=False, +verbose_name=_("Hide votes to new voters"), help_text=_("Check this option to \ +hide poll results to new users")) + open = models.BooleanField(default=True, +verbose_name=_("State of the poll"), help_text=_("Uncheck this option to close \ +the poll/check this option to reopen it")) + + def getTypeLabel(self): + idx = [type[0] for type in self.TYPE].index(self.type) + return Poll.TYPE[idx][1] + + def checkForErasement(self): + '''Check if the poll has to be deleted''' + if not DAYS_TO_LIVE: + return + now = datetime.datetime.now() + dtl = datetime.timedelta(days=DAYS_TO_LIVE) + if self.modification_date + dtl > now: + return + voters = Voter.objects.filter(poll=self) + for voter in voters: + if voter.modification_date + dtl > now: + return + for voter in voters: + voter.user.delete() + voter.delete() + comments = Comment.objects.filter(poll=self) + for comment in comments: + comment.delete() + self.delete() + + def getChoices(self): + """ + Get choices associated to this vote""" + return Choice.objects.filter(poll=self) + + def reorder(self): + """ + Reorder choices of the poll""" + if not self.dated_choices: + return + choices = self.getChoices() + sort_fct = lambda x:datetime.datetime.strptime(x.name, + '%Y-%m-%d %H:%M:%S') + choices = sorted(choices, key=sort_fct) + for idx, choice in enumerate(choices): + choice.order = idx + choice.save() + + class Admin: + pass + class Meta: + ordering = ['-modification_date'] + def __unicode__(self): + return self.name + +class Comment(models.Model): + '''Comment for a poll''' + poll = models.ForeignKey(Poll) + author_name = models.CharField(max_length=100) + text = models.CharField(max_length=1000) + date = models.DateTimeField(auto_now_add=True) + class Meta: + ordering = ['date'] + +class Voter(models.Model): + user = models.ForeignKey(PollUser) + poll = models.ForeignKey(Poll) + creation_date = models.DateTimeField(auto_now_add=True) + modification_date = models.DateTimeField(auto_now=True) + class Meta: + ordering = ['creation_date'] + def __unicode__(self): + return _("Vote from %(user)s") % {'user':self.user.name} + def getVotes(self, choice_ids): + '''Get votes for a subset of choices + ''' + query = Vote.objects.filter(voter=self) + query = query.extra(where=['choice_id IN (%s)' \ + % ",".join([str(choice_id) for choice_id in choice_ids])]) + return list(query.order_by('choice')) + +class Choice(models.Model): + poll = models.ForeignKey(Poll) + name = models.CharField(max_length=200) + order = models.IntegerField() + limit = models.IntegerField(null=True, blank=True) + available = models.BooleanField(default=True) + class Admin: + pass + class Meta: + ordering = ['order'] + + def get_date(self): + if not self.poll.dated_choices: + return self.name + return datetime.datetime.strptime(self.name, '%Y-%m-%d %H:%M:%S') + + def set_date(self, value): + self._date = value + #if not self.poll.dated_choices: + # self.name = value + #self.name = datetime.strftime(value, '%Y-%m-%d %H:%M:%S') + date = property(get_date, set_date) + + def getSum(self, balanced_poll=None): + '''Get the sum of votes for this choice''' + sum = 0 + for vote in Vote.objects.filter(choice=self, value__isnull=False): + sum += vote.value + if balanced_poll: + return sum/2 + return sum + + def changeOrder(self, idx=1): + ''' + Change a choice in the list + ''' + if (self.order + idx) < 0: + return + choices = Choice.objects.filter(poll=self.poll) + if self.order + idx > len(choices): + return + new_order = self.order + idx + for choice in choices: + if choice == self: + continue + if idx < 0 and choice.order < self.order \ + and choice.order >= new_order: + choice.order += 1 + choice.save() + if idx > 0 and choice.order > self.order \ + and choice.order <= new_order: + choice.order -= 1 + choice.save() + self.order = new_order + self.save() + +class Vote(models.Model): + voter = models.ForeignKey(Voter) + choice = models.ForeignKey(Choice) + VOTE = ((1, (_('Yes'), _('Yes'))), + (0, (_('No'), _('Maybe')), ), + (-1, (_('No'), _('No'))),) + value = models.IntegerField(choices=VOTE, blank=True, null=True) |