view polls/models.py @ 943:cf9918328c64

Haystack tweaks for Django 1.7.7. I had to upgrade to Haystack 2.3.1 to get it to work with Django 1.7.7. I also had to update the Xapian backend. But I ran into problems. On my laptop anyway (Ubuntu 14.0.4), xapian gets mad when search terms are greater than 245 chars (or something) when indexing. So I created a custom field that would simply omit terms greater than 64 chars and used this field everywhere I previously used a CharField. Secondly, the custom search form was broken now. Something changed in the Xapian backend and exact searches stopped working. Fortunately the auto_query (which I was using originally and broke during an upgrade) started working again. So I cut the search form back over to doing an auto_query. I kept the form the same (3 fields) because I didn't want to change the form and I think it's better that way.
author Brian Neal <bgneal@gmail.com>
date Wed, 13 May 2015 20:25:07 -0500
parents ee87ea74d46b
children eeaf387803c6
line wrap: on
line source
"""
Models for the Polls application.

"""
import datetime

from django.contrib.auth.models import User
from django.db import models
from django.db.models import Q


class PollManager(models.Manager):
    """Manager for the Poll model"""

    def get_current_polls(self):
        now = datetime.datetime.now()
        return self.filter(
                Q(is_enabled=True),
                Q(start_date__lte=now),
                Q(end_date__isnull=True) | Q(end_date__gte=now))

    def get_old_polls(self):
        now = datetime.datetime.now()
        return self.filter(
                is_enabled=True,
                end_date__isnull=False,
                end_date__lt=now)


class Poll(models.Model):
    """Model to represent polls"""
    start_date = models.DateTimeField(db_index=True,
            help_text='Date/time the poll will be eligible for voting.',)
    end_date = models.DateTimeField(blank=True, null=True, db_index=True,
            help_text='Date/time the poll will be ineligible for voting. '
                'Leave blank for an open ended poll.')
    is_enabled = models.BooleanField(default=True, db_index=True,
            help_text='Check to allow the poll to be viewed on the site.')
    question = models.CharField(max_length=200)

    objects = PollManager()

    def __unicode__(self):
        return self.question

    class Meta:
        ordering = ('-start_date', )
        get_latest_by = 'start_date'

    @models.permalink
    def get_absolute_url(self):
        return ('polls-detail', [], {'poll_id': str(self.id)})

    def results(self):
        """
        Returns a tuple; element 0 is the total votes, element 1 is a list of
        {choice, votes, pct}
        """
        choices = []
        total_votes = 0
        for choice in self.choice_set.all():
            total_votes += choice.votes
            choices.append({'choice': choice.choice, 'votes': choice.votes, 'pct': 0.0})

        if total_votes > 0:
            for choice in choices:
                choice['pct'] = float(choice['votes']) / total_votes * 100.0

        return (total_votes, choices)

    def _total_votes(self):
        """
        Returns the number of votes cast in this poll to date.

        """
        if not hasattr(self, '_total_votes_cache'):
            self._total_votes_cache = sum(choice.votes for choice in
                                            self.choice_set.all())
        return self._total_votes_cache
    total_votes = property(_total_votes)

    def is_open(self):
        now = datetime.datetime.now()
        return self.start_date <= now and (not self.end_date or now <= self.end_date)

    def can_comment_on(self):
        return self.is_open()


class Choice(models.Model):
    """Model for poll choices"""
    poll = models.ForeignKey(Poll)
    choice = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    voters = models.ManyToManyField(User, blank=True)

    def __unicode__(self):
        return self.choice