comparison gpp/polls/models.py @ 439:1f139de929c4

Fixing #216; added anti-ballot stuffing feature to the polls application.
author Brian Neal <bgneal@gmail.com>
date Sat, 21 May 2011 19:55:48 +0000
parents cb121a3abf46
children ac9217eef610
comparison
equal deleted inserted replaced
438:524fd1b3919a 439:1f139de929c4
1 """ 1 """
2 Models for the Polls application. 2 Models for the Polls application.
3 3
4 """ 4 """
5 import datetime 5 import datetime
6
7 from django.contrib.auth.models import User
6 from django.db import models 8 from django.db import models
7 from django.db.models import Q 9 from django.db.models import Q
8 10
9 11
10 class PollManager(models.Manager): 12 class PollManager(models.Manager):
11 """Manager for the Poll model""" 13 """Manager for the Poll model"""
12 14
13 def get_current_polls(self): 15 def get_current_polls(self):
14 now = datetime.datetime.now() 16 now = datetime.datetime.now()
15 return self.filter( 17 return self.filter(
16 Q(is_enabled=True), 18 Q(is_enabled=True),
17 Q(start_date__lte=now), 19 Q(start_date__lte=now),
18 Q(end_date__isnull=True) | Q(end_date__gte=now)) 20 Q(end_date__isnull=True) | Q(end_date__gte=now))
19 21
20 def get_old_polls(self): 22 def get_old_polls(self):
21 now = datetime.datetime.now() 23 now = datetime.datetime.now()
22 return self.filter( 24 return self.filter(
23 Q(is_enabled=True), 25 is_enabled=True,
24 Q(end_date__isnull=False), 26 end_date__isnull=False,
25 Q(end_date__lt=now)) 27 end_date__lt=now)
26 28
27 29
28 class Poll(models.Model): 30 class Poll(models.Model):
29 """Model to represent polls""" 31 """Model to represent polls"""
30 start_date = models.DateTimeField(db_index=True, 32 start_date = models.DateTimeField(db_index=True,
31 help_text='Date/time the poll will be eligible for voting.',) 33 help_text='Date/time the poll will be eligible for voting.',)
32 end_date = models.DateTimeField(blank=True, null=True, db_index=True, 34 end_date = models.DateTimeField(blank=True, null=True, db_index=True,
33 help_text='Date/time the poll will be ineligible for voting. ' 35 help_text='Date/time the poll will be ineligible for voting. '
34 'Leave blank for an open ended poll.') 36 'Leave blank for an open ended poll.')
35 is_enabled = models.BooleanField(default=True, db_index=True, 37 is_enabled = models.BooleanField(default=True, db_index=True,
36 help_text='Check to allow the poll to be viewed on the site.') 38 help_text='Check to allow the poll to be viewed on the site.')
37 question = models.CharField(max_length=200) 39 question = models.CharField(max_length=200)
38 40
39 objects = PollManager() 41 objects = PollManager()
40 42
41 def __unicode__(self): 43 def __unicode__(self):
42 return self.question 44 return self.question
43 45
44 class Meta: 46 class Meta:
45 ordering = ('-start_date', ) 47 ordering = ('-start_date', )
46 get_latest_by = 'start_date' 48 get_latest_by = 'start_date'
47 49
48 @models.permalink 50 @models.permalink
49 def get_absolute_url(self): 51 def get_absolute_url(self):
50 return ('polls.views.poll_detail', [str(self.id)]) 52 return ('polls-detail', [], {'poll_id': str(self.id)})
51 53
52 def results(self): 54 def results(self):
53 """ 55 """
54 Returns a tuple; element 0 is the total votes, element 1 is a list of 56 Returns a tuple; element 0 is the total votes, element 1 is a list of
55 {choice, votes, pct} 57 {choice, votes, pct}
56 """ 58 """
57 choices = [] 59 choices = []
58 total_votes = 0 60 total_votes = 0
59 for choice in self.choice_set.all(): 61 for choice in self.choice_set.all():
60 total_votes += choice.votes 62 total_votes += choice.votes
61 choices.append({'choice': choice.choice, 'votes': choice.votes, 'pct': 0.0}) 63 choices.append({'choice': choice.choice, 'votes': choice.votes, 'pct': 0.0})
62 64
63 if total_votes > 0: 65 if total_votes > 0:
64 for choice in choices: 66 for choice in choices:
65 choice['pct'] = float(choice['votes']) / total_votes * 100.0 67 choice['pct'] = float(choice['votes']) / total_votes * 100.0
66 68
67 return (total_votes, choices) 69 return (total_votes, choices)
68 70
69 def is_open(self): 71 def total_votes(self):
70 now = datetime.datetime.now() 72 """
71 return self.start_date <= now and (not self.end_date or now <= self.end_date) 73 Returns the number of votes cast in this poll to date.
72 74
73 def can_comment_on(self): 75 """
74 return self.is_open() 76 return sum(choice.votes for choice in self.choice_set.all())
77
78 def is_open(self):
79 now = datetime.datetime.now()
80 return self.start_date <= now and (not self.end_date or now <= self.end_date)
81
82 def can_comment_on(self):
83 return self.is_open()
75 84
76 85
77 class Choice(models.Model): 86 class Choice(models.Model):
78 """Model for poll choices""" 87 """Model for poll choices"""
79 poll = models.ForeignKey(Poll) 88 poll = models.ForeignKey(Poll)
80 choice = models.CharField(max_length = 200) 89 choice = models.CharField(max_length=200)
81 votes = models.IntegerField(default = 0) 90 votes = models.IntegerField(default=0)
91 voters = models.ManyToManyField(User, blank=True)
82 92
83 def __unicode__(self): 93 def __unicode__(self):
84 return self.choice 94 return self.choice