bgneal@367: """
gremmie@1: Models for the Polls application.
gremmie@1: 
bgneal@367: """
gremmie@1: import datetime
bgneal@439: 
bgneal@439: from django.contrib.auth.models import User
gremmie@1: from django.db import models
gremmie@1: from django.db.models import Q
gremmie@1: 
gremmie@1: 
gremmie@1: class PollManager(models.Manager):
bgneal@439:     """Manager for the Poll model"""
gremmie@1: 
bgneal@439:     def get_current_polls(self):
bgneal@439:         now = datetime.datetime.now()
bgneal@439:         return self.filter(
bgneal@439:                 Q(is_enabled=True),
bgneal@439:                 Q(start_date__lte=now),
bgneal@439:                 Q(end_date__isnull=True) | Q(end_date__gte=now))
gremmie@1: 
bgneal@439:     def get_old_polls(self):
bgneal@439:         now = datetime.datetime.now()
bgneal@439:         return self.filter(
bgneal@439:                 is_enabled=True,
bgneal@439:                 end_date__isnull=False,
bgneal@439:                 end_date__lt=now)
gremmie@1: 
gremmie@1: 
gremmie@1: class Poll(models.Model):
bgneal@439:     """Model to represent polls"""
bgneal@439:     start_date = models.DateTimeField(db_index=True,
bgneal@439:             help_text='Date/time the poll will be eligible for voting.',)
bgneal@439:     end_date = models.DateTimeField(blank=True, null=True, db_index=True,
bgneal@439:             help_text='Date/time the poll will be ineligible for voting. '
bgneal@439:                 'Leave blank for an open ended poll.')
bgneal@439:     is_enabled = models.BooleanField(default=True, db_index=True,
bgneal@439:             help_text='Check to allow the poll to be viewed on the site.')
bgneal@439:     question = models.CharField(max_length=200)
gremmie@1: 
bgneal@439:     objects = PollManager()
gremmie@1: 
bgneal@439:     def __unicode__(self):
bgneal@439:         return self.question
gremmie@1: 
bgneal@439:     class Meta:
bgneal@439:         ordering = ('-start_date', )
bgneal@439:         get_latest_by = 'start_date'
gremmie@1: 
bgneal@439:     @models.permalink
bgneal@439:     def get_absolute_url(self):
bgneal@439:         return ('polls-detail', [], {'poll_id': str(self.id)})
gremmie@1: 
bgneal@439:     def results(self):
bgneal@439:         """
bgneal@439:         Returns a tuple; element 0 is the total votes, element 1 is a list of
bgneal@439:         {choice, votes, pct}
bgneal@439:         """
bgneal@439:         choices = []
bgneal@439:         total_votes = 0
bgneal@439:         for choice in self.choice_set.all():
bgneal@439:             total_votes += choice.votes
bgneal@439:             choices.append({'choice': choice.choice, 'votes': choice.votes, 'pct': 0.0})
gremmie@1: 
bgneal@439:         if total_votes > 0:
bgneal@439:             for choice in choices:
bgneal@439:                 choice['pct'] = float(choice['votes']) / total_votes * 100.0
gremmie@1: 
bgneal@439:         return (total_votes, choices)
gremmie@1: 
bgneal@440:     def _total_votes(self):
bgneal@439:         """
bgneal@439:         Returns the number of votes cast in this poll to date.
gremmie@1: 
bgneal@439:         """
bgneal@440:         if not hasattr(self, '_total_votes_cache'):
bgneal@440:             self._total_votes_cache = sum(choice.votes for choice in
bgneal@440:                                             self.choice_set.all())
bgneal@440:         return self._total_votes_cache
bgneal@440:     total_votes = property(_total_votes)
bgneal@439: 
bgneal@439:     def is_open(self):
bgneal@439:         now = datetime.datetime.now()
bgneal@439:         return self.start_date <= now and (not self.end_date or now <= self.end_date)
bgneal@439: 
bgneal@439:     def can_comment_on(self):
bgneal@439:         return self.is_open()
gremmie@1: 
gremmie@1: 
gremmie@1: class Choice(models.Model):
bgneal@439:     """Model for poll choices"""
bgneal@439:     poll = models.ForeignKey(Poll)
bgneal@439:     choice = models.CharField(max_length=200)
bgneal@439:     votes = models.IntegerField(default=0)
bgneal@439:     voters = models.ManyToManyField(User, blank=True)
gremmie@1: 
bgneal@439:     def __unicode__(self):
bgneal@439:         return self.choice