• Stars
    star
    110
  • Rank 316,770 (Top 7 %)
  • Language
    Python
  • License
    Other
  • Created over 9 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A lightweight library designed to handle repeating and one-off event occurrences for display on a website.

django-eventtools is a lightweight library designed to handle repeating and one-off event occurrences for display on a website.

Circle CI codecov Latest Version

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:

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 note that a from_date filtered queryset may contain false positives because it's not possible to tell for sure if a event will happen after a certain date without evaluating repetition rules, meaning it can't be part of a database query. If you need a queryset filtered exactly, pass exact=True - this will filter the queryset by id, based on generated occurrences. Be careful with this option though 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)

Note to_date filtering is always accurate, because the query only needs to consider the event's first occurrence.

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. To customise the available options, set EVENTTOOLS_REPEAT_CHOICES in your django settings. The default value is

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:

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

More Repositories

1

acme-webfaction

Automatically install and renew letsencrypt ssl certificates on webfaction
Python
30
star
2

django-simple-search

Django simple search provides the same functionality and convenience that search_fields does in the django admin.
Python
27
star
3

django-next-prev

Django utility to retrieve the next or previous object, given a current object and a queryset.
Python
25
star
4

django-projectmanager

This project is no longer maintained. Check out https://timesheet.gregbrown.co - the time tracking application which grew out of this codebase.
JavaScript
20
star
5

django-baseclasses

A set of reusable base classes and helpers for django
Python
9
star
6

djangocms2000

Flexible Django CMS with edit-in-place capability. Master branch is stable
Python
8
star
7

hashban.js

hashban.js is a plugin to streamline the addition of ajax-style page transitions to a website.
JavaScript
6
star
8

django-fileman

django-fileman adds user-uploaded static files to the django admin (i.e. images, media, documents) and integrates with tinymce
Python
6
star
9

django-pubtools

django-pubtools is a helper library for creating publishable django models.
Python
6
star
10

django-countryip

Provides a utility to import countries and IP ranges into your database via the Maxmind csv country database. The Country model's manager provides a helpful 'for_ip()' method which you can use to look up a country based on an IP. Cloned from http://code.google.com/p/django-countryip/
Python
5
star
11

ScrollBalance.js

Intelligently uses position: fixed to combat unsightly gaps in multi-column layouts, when columns are of different heights. See http://gregplaysguitar.github.io/ScrollBalance.js/ for a demo.
HTML
4
star
12

django-trolley

This is deprecated, so don't use it
Python
4
star
13

notepad

Lightweight notepad web app written in Flask
CSS
3
star
14

django-utilities

Deprecated - don't use this
3
star
15

django-locationpicker

Python
2
star
16

tinymce

1
star
17

jquery-aggregate

JavaScript
1
star
18

glamkit

Python
1
star
19

react-object-input

A React component which facilitates user-friendly editing of plain javascript objects.
TypeScript
1
star