<filename>eventtools/models/xseason.py
from datetime import date
from django.db import models
from eventtools.utils.pprint_timespan \
    import pprint_datetime_span, pprint_date_span
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext, ugettext_lazy as _

class SeasonQSFN(object):
    def current_on(self, date):
        return self.filter(start__lte=date, end__gte=date)
        
    def forthcoming_on(self, date):
        return self.filter(start__gt=date)
        
    def previous_on(self, date):
        return self.filter(end__lt=date)

class SeasonQuerySet(models.query.QuerySet, SeasonQSFN):
    pass #all the goodness is inherited from SeasonQSFN

class SeasonManagerType(type):
    """
    Injects proxies for all the queryset's functions into the Manager
    """
    @staticmethod
    def _fproxy(name):
        def f(self, *args, **kwargs):
            return getattr(self.get_query_set(), name)(*args, **kwargs)
        return f

    def __init__(cls, *args):
        for fname in dir(SeasonQSFN):
            if not fname.startswith("_"):
                setattr(cls, fname, SeasonManagerType._fproxy(fname))
        super(SeasonManagerType, cls).__init__(*args)

class SeasonManager(models.Manager):    
    __metaclass__ = SeasonManagerType

    def get_query_set(self): 
        return SeasonQuerySet(self.model)


class XSeasonModel(models.Model):
    """
    Describes an entity which takes place between start and end dates. For
    example, a festival or exhibition.
    
    The fields are optional - both omitted means 'ongoing'.
    """

    start = models.DateField(null=True, blank=True, verbose_name=_('start'))
    end = models.DateField(null=True, blank=True, verbose_name=_('end'))
    
    objects = SeasonManager()

    class Meta:
        abstract = True
        
    def clean(self):
        if (self.start is not None and self.end is None) or \
            (self.end is not None and self.start is None):
            raise ValidationError('Start and End must both be provided, or blank')

        if self.start > self.end:
            raise ValidationError('Start must be earlier than End')
            
    def season(self):
        """
        Returns a string describing the first and last dates of this event.
        """        
        if self.start and self.end:
            first = self.start
            last = self.end
        
            return pprint_date_span(first, last)
        
        return None
        
    def __unicode__(self):
        return self.season()

    def is_finished(self):
        return self.end < date.today()

<filename>eventtools/models/xseason.py
from datetime import date
from django.db import models
from eventtools.utils.pprint_timespan \
    import pprint_datetime_span, pprint_date_span
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext, ugettext_lazy as _

class SeasonQSFN(object):
    def current_on(self, date):
        return self.filter(start__lte=date, end__gte=date)
        
    def forthcoming_on(self, date):
        return self.filter(start__gt=date)
        
    def previous_on(self, date):
        return self.filter(end__lt=date)

class SeasonQuerySet(models.query.QuerySet, SeasonQSFN):
    pass #all the goodness is inherited from SeasonQSFN

class SeasonManagerType(type):
    """
    Injects proxies for all the queryset's functions into the Manager
    """
    @staticmethod
    def _fproxy(name):
        def f(self, *args, **kwargs):
            return getattr(self.get_query_set(), name)(*args, **kwargs)
        return f

    def __init__(cls, *args):
        for fname in dir(SeasonQSFN):
            if not fname.startswith("_"):
                setattr(cls, fname, SeasonManagerType._fproxy(fname))
        super(SeasonManagerType, cls).__init__(*args)

class SeasonManager(models.Manager):    
    __metaclass__ = SeasonManagerType

    def get_query_set(self): 
        return SeasonQuerySet(self.model)


class XSeasonModel(models.Model):
    """
    Describes an entity which takes place between start and end dates. For
    example, a festival or exhibition.
    
    The fields are optional - both omitted means 'ongoing'.
    """

    start = models.DateField(null=True, blank=True, verbose_name=_('start'))
    end = models.DateField(null=True, blank=True, verbose_name=_('end'))
    
    objects = SeasonManager()

    class Meta:
        abstract = True
        
    def clean(self):
        if (self.start is not None and self.end is None) or \
            (self.end is not None and self.start is None):
            raise ValidationError('Start and End must both be provided, or blank')

        if self.start > self.end:
            raise ValidationError('Start must be earlier than End')
            
    def season(self):
        """
        Returns a string describing the first and last dates of this event.
        """        
        if self.start and self.end:
            first = self.start
            last = self.end
        
            return pprint_date_span(first, last)
        
        return None
        
    def __unicode__(self):
        return self.season()

    def is_finished(self):
        return self.end < date.today()

#all the goodness is inherited from SeasonQSFN Injects proxies for all the queryset's functions into the Manager Describes an entity which takes place between start and end dates. For     example, a festival or exhibition.          The fields are optional - both omitted means 'ongoing'. Returns a string describing the first and last dates of this event.