Metadata-Version: 1.1
Name: django-eventtools
Version: 1.0.1
Summary: Recurring event tools for django
Home-page: https://github.com/gregplaysguitar/django-eventtools
Author: Greg Brown
Author-email: greg@gregbrown.co.nz
License: BSD License
Description: django-eventtools is a lightweight library designed to handle repeating
        and one-off event occurrences for display on a website.
        
        `Circle
        CI <https://circleci.com/gh/gregplaysguitar/django-eventtools>`__
        `codecov <https://codecov.io/gh/gregplaysguitar/django-eventtools>`__
        `Latest Version <https://pypi.python.org/pypi/django-eventtools/>`__
        
        Installation
        ------------
        
        Download the source from https://pypi.python.org/pypi/django-eventtools/
        and run ``python setup.py install``, or:
        
        ::
        
           > pip install django-eventtools
        
        Django 1.8 or higher is required.
        
        Setup
        -----
        
        Given the following models:
        
        .. code:: python
        
           from django.db import models
        
           from eventtools.models import BaseEvent, BaseOccurrence
        
        
           class MyEvent(BaseEvent):
               title = models.CharField(max_length=100)
        
        
           class MyOccurrence(BaseOccurrence):
               event = models.ForeignKey(MyEvent)
        
        Usage
        -----
        
        Create a sample event & occurrences
        
        ::
        
           >>> from datetime import datetime
           >>> from myapp.models import MyEvent
           >>> event = MyEvent.objects.create(title='Test event')
           >>> once_off = MyOccurrence.objects.create(
                   event=event,
                   start=datetime(2016, 1, 1, 12, 0),
                   end=datetime(2016, 1, 1, 2, 0))
           >>> christmas = MyOccurrence.objects.create(
                   event=event,
                   start=datetime(2015, 12, 25, 7, 0),
                   end=datetime(2015, 12, 25, 22, 0),
                   repeat='RRULE:FREQ=YEARLY')
           >>> daily = MyOccurrence.objects.create(
                   event=event,
                   start=datetime(2016, 1, 1, 7, 0),
                   end=datetime(2016, 1, 1, 8, 0),
                   repeat='RRULE:FREQ=DAILY')
        
        Event and Occurrence instances, and their associated querysets, all
        support the ``all_occurrences`` method, which takes two optional
        arguments - ``from_date`` and ``to_date``, which may be dates or
        datetimes. ``from_date`` and ``to_date`` default to ``None``. The method
        returns a python generator yielding tuples in the format
        ``(start, end, instance)`` - for example:
        
        ::
        
           >>> MyEvent.objects.all().all_occurrences()
           >>> event.all_occurrences(from_date=datetime(2015, 1, 1, 10, 0))
           >>> event.occurrence_set.all().all_occurrences(to_date=date(2016, 1, 1))
           >>> occurrence.all_occurrences(from_date=date(2016, 1, 1),
                                          to_date=date(2016, 12, 31))
        
        ``instance`` is an instance of the corresponding BaseOccurrence
        subclass.
        
        A ``next_occurrence`` method is also provided, taking the same
        arguments, but returning a single occurrence tuple.
        
        ::
        
           >>> event.next_occurrence()
           >>> event.next_occurrence(from_date=date(2016, 1, 1))
        
        The method ``first_occurrence`` also returns a single occurrence tuple,
        but takes no arguments.
        
        Queryset filtering
        ~~~~~~~~~~~~~~~~~~
        
        Event and Occurrence querysets can be filtered, but due to uncertainty
        with repetitions, ``from_date`` filtering is only an approximation
        (whereas ``to_date`` filtering is accurate). If you need a queryset
        filtered exactly, pass ``exact=True`` - this will filter using generated
        occurrences but still return a queryset - but be careful with this as it
        may be very slow and/or CPU-hungry. For example
        
        ::
        
           >>> MyEvent.objects.for_period(from_date=date(2015, 1, 1),
                                        to_date=date(2015, 12, 31))
           >>> event.occurrence_set.for_period(from_date=date(2015, 1, 1), exact=True)
        
        Sorting querysets
        ~~~~~~~~~~~~~~~~~
        
        Event and Occurrence querysets can also be sorted by their next
        occurrence using the ``sort_by_next`` method. By default this sorts
        instances by their first occurrence; the optional ``from_date`` argument
        will sort by the next occurrence after ``from_date``. For example
        
        ::
        
           >>> MyEvent.objects.all().sort_by_next()
           >>> event.occurrence_set.for_period(from_date=date(2015, 1, 1)) \
           >>>      .sort_by_next(date(2015, 1, 1))
        
        Note that this method returns a sorted list, not a queryset.
        
        Custom repeat intervals
        -----------------------
        
        Occurrences can repeat using any interval that can be expressed as an
        `rrulestr <https://labix.org/python-dateutil#head-e987b581aebacf25c7276d3e9214385a12a091f2>`__.
        To customise the available options, set ``EVENTTOOLS_REPEAT_CHOICES`` in
        your django settings. The default value is
        
        .. code:: python
        
           EVENTTOOLS_REPEAT_CHOICES = (
               ("RRULE:FREQ=DAILY", 'Daily'),
               ("RRULE:FREQ=WEEKLY", 'Weekly'),
               ("RRULE:FREQ=MONTHLY", 'Monthly'),
               ("RRULE:FREQ=YEARLY", 'Yearly'),
           )
        
        Set ``EVENTTOOLS_REPEAT_CHOICES = None`` to make repeat a plain-text
        field.
        
        Occurrence cancellations or modifications
        -----------------------------------------
        
        Cancelling or modifying a single occurrence repetition is not currently
        supported, but can be implemented by overriding a couple of methods. For
        example, the following allows cancellations or one-off modifications to
        the start time of a repetition:
        
        .. code:: python
        
           from eventtools.models import (BaseEvent, BaseOccurrence, default_naive)
           from django.db import models
        
        
           class MyEvent(BaseEvent):
               pass
        
        
           class MyEventOccurrence(BaseOccurrence):
               event = models.ForeignKey(MyEvent)
               overrides = models.ManyToManyField('MyEventOccurrenceOverride', blank=True)
        
               def get_repeater(self):
                   rule = super().get_repeater()  # gets rruleset from parent method
                   ruleset.rrule(rule)
                   for override in self.overrides.all():
                       ruleset.exdate(default_naive(override.start))  # remove occurrence
                       if override.modified_start:  # reschedule occurrence if defined
                           ruleset.rdate(default_naive(override.modified_start))
                   return ruleset
        
        
           class MyEventOccurrenceOverride(models.Model):
               start = models.DateTimeField()  # must match targeted repetition exactly
               # new start, leave blank to cancel
               modified_start = models.DateTimeField(blank=True, null=True)  
        
        Note that start times must match exactly, so if the MyEventOccurrence
        start is changed, any previously-matching overrides will no longer be
        applied.
        
        Running tests
        -------------
        
        Use tox (https://pypi.python.org/pypi/tox):
        
        ::
        
           > pip install tox
           > cd path-to/django-eventtools
           > tox
        
Platform: any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Framework :: Django
