Welcome to DjangoSchedule’s documentation!

DjangoSchedule is an open-source calendaring application.

Install

Currently undocumented

A Quick Overview

What is an Event?

An event doesn’t have any date or time associated with it just a rule for how it recurs. In a way it designates a set of occurrences. A weekly staff meeting is a perfect example. A weekly staff meeting is an event, it says what it is and how often it recurs. Now if we were to say Tuesday’s staff meeting, thats an occurrence. That is an a specific element in the set of occurrences designated by weekly staff meeting.

There is an exception, and that is the “one-time” event. If your boss calls and sets up an meeting today at 3. Thats a one-time event. Its only going to happen this one time. That doesn’t mean its an occurrence. It just means that its an event which represents a set of occurrences that only has one occurrence in it.

What is an Occurrence?

An occurrence is an instance of an event. If we have an event and it is Weekly staff meetings which occur every tuesday then next Tuesday’s staff meeting is an occurrence.

What does persisted Occurrences mean?

Occurrences are generated programatically. This is because we can not store all of the occurrences in the database, because there could be infinite occurrences. But we still want to be able to persist data about occurrences. Like, canceling an occurrence, moving an occurrence, storing a list of attendees with the occurrence. This is done lazily. An occurrence is generated programatically until it needs to be saved to the database. When you use any function to get an occurrence, it will be completely transparent whether it was generated programatically or whether it is persisted (except that persisted ones will have a pk). Just treat them like they are persisted and you shouldn’t run into any trouble.

What is a Rule?

A rule defines how and event will recur. As of right now, there are no rules included with the app, so you will have to create your own. Doing this is somewhat straight forward

Accessing Occurrences with an Event

Because some Event can recur indefinitely, you can not have a function like, event.get_all_occurrences(), because that would be an infinite list. So, there are two ways of getting occurrences given an event.

get_occurrences(start, end)

This gives you a list of all occurrences that occur inclusively after start and exclusively before end. When we say occur, that means that they exist at all between start and end. If occurrence ends 10 seconds after start then it will be in the list, and if an occurrence starts 10 seconds before end then it will also be in the list.

occurrences_after(after)

This method produces a generator that generates events inclusively after the given datetime after. If no date is given then it uses now.

Accessing Occurrences from lists of Events

You are often going to have a list of events and want to get occurrences from them. To do this you can use Periods, and EventListManagers.

Periods

One of the goals of DjangoSchedule is to make occurrence generation and persistence easy. To do this it creates simple classes for accessing these occurrences. These are Periods. Period is an object that is initiated with an iterable object of events, a start datetime, and an end datetime.

It is common to subclass Period for common periods of time. Some of these already exist in the project. Year, Month, Week, Day

Expect more in the future: Hour, HalfHour

Period Base Class

This is the base class from which all other periods inherit. It contains all of the base functionality for retrieving occurrences. It is instantiated with a list of events, a start date, and an end date. The start date is inclusive, the end date is exclusive. ie [start, end)

>>> p = Period(datetime.datetime(2008,4,1,0,0))

get_occurrences()

This method is for getting the occurrences from the list of passed in events. It returns the occurrences that exist in the period for every event. If I have a list of events my_events, and I want to know all of the occurrences from today to next week I simply create a Period object and then call get_occurrences. It will return a sorted list of Occurrences.

import datetime

today = datetime.datetime.now()
this_week = Period(my_events, today, today+datetime.timedelta(days=7))
this_week.get_occurrences()

classify_occurrence(occurrence)

You use this method to determine how the Occurrence occurrence relates to the period. This method returns a dictionary. The keys are "class" and "occurrence". The class key returns a a number from 0 to 3 and the occurrence key returns the occurrence.

Classes:

0: Only started during this period.

1: Started and ended during this period.

2: Didn’t start or end in this period, but does exist during this period.

3: Only ended during this period.

get_occurrence_partials()

This method is used for getting all the occurrences, but getting them as classified occurrences. Simply it runs classify_occurrence on each occurrence in get_occurrence and returns that list.

import datetime

today = datetime.datetime.now()
this_week = Period(my_events, today, today+datetime.timedelta(days=7))
this_week.get_occurrences() == [classified_occurrence['occurrence'] for classified_occurrence in this_week.get_occurrence_partials()]

has_occurrence()

This method returns whether there are any occurrences in this period

Year

The year period is instaniated with a list of events and a date or datetime object. It will resemble the year in which that date exists.

>>> p = Year(events, datetime.datetime(2008,4,1))
>>> p.start
datetime.datetime(2008, 1, 1, 0, 0)
>>> p.end
datetime.datetime(2009, 1, 1, 0, 0)
>>> -Remember start is inclusive and end is exclusive

get_months()

This function returns 12 Month objects which resemble the 12 months in the Year period.

Month

The Month period is instantiated with a list of events and a date or datetime object. It resembles the month that contains the date or datetime object that was passed in.

>>> p = Month(events, datetime.datetime(2008,4,4))
>>> p.start
datetime.datetime(2008, 4, 1, 0, 0)
>>> p.end
datetime.datetime(2008, 5, 1, 0, 0)
>>> -Remember start is inclusive and end is exclusive

get_weeks()

This method returns a list of Week objects that occur at all during that month. The week does not have to be fully encapsulated in the month just have exist in the month at all

get_days()

This method returns a list of Day objects that occur during the month.

get_day(day_number)

This method returns a specific day in a year given its day number.

Week

The Week period is instantiated with a list of events and a date or datetime object. It resembles the week that contains the date or datetime object that was passed in.

>>> p = Week(events, datetime.datetime(2008,4,1))
>>> p.start
datetime.datetime(2008, 3, 30, 0, 0)
>>> p.end
datetime.datetime(2008, 4, 6, 0, 0)
>>> -Remember start is inclusive and end is exclusive

get_days()

This method returns the 7 Day objects that represent the days in a Week period.

Day

The Day period is instantiated with a list of events and a date or datetime object. It resembles the day that contains the date or datetime object that was passed in.

>>> p = Day(events, datetime.datetime(2008,4,1))
>>> p.start
datetime.datetime(2008, 4, 1, 0, 0)
>>> p.end
datetime.datetime(2008, 4, 2, 0, 0)
>>> -Remember start is inclusive and end is exclusive

Utilities

There are some utility classes found in the utils module that help with certain tasks.

EventListManager

EventListManager objects are instantiated with a list of events. That list of events dictates the following methods

occurrences_after(after)

Creates a generator that produces the next occurrence inclusively after the datetime after.

OccurrenceReplacer

If you get more into the internals of django-schedule, and decide to create your own method for producing occurrences, instead of using one of the public facing methods for this, you are going to want to replace the occurrence you produce with a persisted one, if a persisted one exists. To facilitate this in a standardized way you have the OccurrenceReplacer class.

To instantiate it you give it the pool of persisted occurrences you would like to check in.

>>> persisted_occurrences = my_event.occurrence_set.all()
>>> occ_replacer = OccurrenceReplacer(persisted_occurrences)

Now you have two convenient methods

get_occurrence(occurrence)

This method returns either the passed in occurrence or the equivalent persisted occurrences from the pool of persisted occurrences this OccurrenceReplacer was instantiated with.

>>> # my_generated_occurrence is an occurrence that was programatically
>>> # generated from an event
>>> occurrence = occ_replacer.get_occurrence(my_generated_occurrence)

has_occurrence(occurrence)

This method returns a boolean. It returns True of the OccurrenceReplacer has an occurrence it would like to replace with the give occurrence, and false if it does not

>>> hasattr(my_generated_occurrence, 'pk')
False
>>> occ_replacer.has_occurrence(my_generated_occurrence)
True
>>> occurrence = occ_replacer.get_occurrence(my_generated_occurrence)
>>> hasattr(occurrence, 'pk')
True
>>> # Now with my_other_occurrence which does not have a persisted counterpart
>>> hasattr(my_other_occurrence, 'pk')
False
>>> occ_replacer.has_occurrence(my_other_occurrence)
False
>>> occurrence = occ_replacer.get_occurrence(my_other_occurrence)
>>> hasattr(occurrence, 'pk')
False

Useful Template Tags

All of the templatetags are located in templatetags/scheduletags.py. You can look at more of them there. I am only going to talk about a few here.

To load the template tags this must be in your template

{% load scheduletags %}

querystring_for_date

Usage
{% querystring_for_date <date>[ <num>] %}

This template tag produces a querystring that describes date. It turns date into a dictionary and then turns that dictionary into a querystring, in this fashion:

>>> date = datetime.datetime(2009,4,1)
>>> querystring_for_date(date)
'?year=2009&month=4&day=1&hour=0&minute=0&second=0'

This is useful when creating links as the calendar_by_period view uses this to display any date besides datetime.datetime.now(). The num argument can be used to say how specific you want to be about the date. If you were displaying a yearly calendar you only care about the year so num would only have to be 1. See the examples below

>>> querystring_for_date(date, num=1)
'?year=2009'
>>> # Now if we only need the month
>>> querystring_for_date(date, num=2)
'?year=2009&month=4'
>>> # Now everything except the seconds
>>> querystring_for_date(date, num=5)
'?year=2009&month=4&day=1&hour=0&minute=0'

Views

calendar

This view is for displaying meta_data about calendars. Upcoming events, Name, description and so on and so forth. It should be noted that this is probably not the best view for displaying a calendar in a traditional sense, i.e. displaying a month calendar or a year calendar, as it does not equip the context with any period objects. If you would like to do this you should use calendar_by_period.

Required Arguments

request
As always the request object
calendar_slug
The slug of the calendar to be displayed

Optional Arguments

template_name
default
‘schedule/calendar.html’

This is the template that will be rendered

Context Variables

calendar
The Calendar object designated by the calendar_slug.

calendar_by_period

This view is for getting a calendar, but also getting periods with that calendar. Which periods you get, is designated with the list periods. You can designate which date you the periods to be initialized to by passing a date in request.GET. See the template tag query_string_for_date

Required Arguments

request
As always the request object
calendar_slug
The slug of the calendar to be displayed

Optional Arguments

template_name
default
‘schedule/calendar_by_period .html’

This is the template that will be rendered

periods
default
[]

This is a list of Period Subclasses that designates which periods you would like to instantiate and put in the context

Context Variables

date
This was the date that was generated from the query string.
periods

this is a dictionary that returns the periods from the list you passed in. If you passed in Month and Day, then your dictionary would look like this

{
    'month': <schedule.periods.Month object>
    'day':   <schedule.periods.Day object>
}

So in the template to access the Day period in the context you simply use periods.day.

calendar
This is the Calendar that is designated by the calendar_slug.
weekday_names
This is for convenience. It returns the local names of weekedays for internationalization.

event

This view is for showing an event. It is important to remember that an event is not an occurrence. Events define a set of reccurring occurrences. If you would like to display an occurrence (a single instance of a recurring event) use occurrence.

Required Arguments

request
As always the request object
event_id
the id of the event to be displayed

Optional Arguments

template_name
default
‘schedule/calendar_by_period.html’

This is the template that will be rendered

Context Variables

event
This is the event designated by the event_id
back_url
this is the url that referred to this view.

occurrence

This view is used to display an occurrence. There are two methods of displaying an occurrence.

Required Arguments

request
As always the request object
event_id
the id of the event that produces the occurrence

from here you need a way to distinguish the occurrence and that involves

occurrence_id
if its persisted

or it requires a distinguishing datetime as designated by the keywords below. This should designate the original start date of the occurrence that you wish to access. Using get_absolute_url from the Occurrence model will help you standardize this.

  • year
  • month
  • day
  • hour
  • minute
  • second

Optional Arguments

template_name
default
‘schedule/calendar_by_period.html’

This is the template that will be rendered

Context Variables

event
the event that produces the occurrence
occurrence
the occurrence to be displayed
back_url
the url from which this request was refered

edit_occurrence

This view is used to edit an occurrence.

Required Arguments

request
As always the request object
event_id
the id for the event

from here you need a way to distinguish the occurrence and that involves

occurrence_id
the id of the occurrence if its persisted

or it requires a distinguishing datetime as designated by the keywords below. This should designate the original start date of the occurrence that you wish to access. Using get_edit_url from the Occurrence model will help you standardize this.

  • year
  • month
  • day
  • hour
  • minute
  • second

Optional Arguments

template_name
default
‘schedule/calendar_by_period.html’

This is the template that will be rendered

Context Variables

form
an instance of OccurrenceForm to be displayed
occurrence
an instance of the occurrence being modified

cancel_occurrence

This view is used to cancel and occurrence. It is worth noting that canceling an occurrence doesn’t stop it from being in occurrence lists or being persisted, it just changes the cancelled flag on the instance. It is import to check this flag when listing occurrences.

Also if this view is requested via POST, it will cancel the event and redirect. If this view is accessed via a GET request it will display a confirmation page.

Required Arguments

request
As always the request object

from here you need a way to distinguish the occurrence and that involves

occurrence_id
if its persisted

or it requires a distinguishing datetime as designated by the keywords below. This should designate the original start date of the occurrence that you wish to access. Using get_cancel_url from the Occurrence model will help you standardize this.

  • year
  • month
  • day
  • hour
  • minute
  • second

Optional Arguments

template_name
default
‘schedule/calendar_by_period.html’

This is the template that will be rendered, if this view is accessed via GET

next
default
the event detail page of occurrence.event

This is the url you wish to be redirected to after a successful cancelation

Context Variables

occurrence
an instance of the occurrence being modified

create_or_edit_event

This view is used for creating or editing events. If it receives a GET request or if given an invalid form in a POST request it will render the template, or else it will redirect.

Required Arguments

request
As always the request object
calendar_id
This is the calendar id of the event being created or edited.

Optional Arguments

template_name
default
‘schedule/calendar_by_period.html’

This is the template that will be rendered

event_id
if you are editing an event, you need to pass in the id of the event, so that the form can be pre-propagated with the correct information and also so save works correctly
next
The url to redirect to upon successful completion or edition.

Context Variables

form
an instance of EventForm to be displayed.
calendar
a Calendar with id=calendar_id

delete_event

This view is for deleting events. If the view is accessed via a POST request it will delete the event. If it is accessed via a GET request it will render a template to ask for confirmation.

Required Arguments

request
As always the request object
event_id
the id of the event to be deleted.

Optional Arguments

template_name
default
‘schedule/calendar_by_period.html’

This is the template that will be rendered

next
The url to redirect to after successful deletion
login_required
default
True

if you want to require a login before deletion happens you can set that here

Context Variables

object
The event object to be deleted

Models

Not Documented yet

Settings

FIRST_DAY_OF_WEEK

This setting determines which day of the week your calendar begins on if your locale doesn’t already set it. Default is 0, which is Sunday.

OCCURRENCE_CANCEL_REDIRECT

This setting controls the behavior of Views.get_next_url(). If set, all calendar modifications will redirect here (unless there is a next set in the request.)

SHOW_CANCELLED_OCCURRENCES

This setting controls the behavior of Period.classify_occurence(). If True, then occurences that have been cancelled will be displayed with a css class of canceled, otherwise they won’t appear at all.

Defaults to False

CHECK_PERMISSION_FUNC

This setting controls the callable used to determine if a user has permission to edit an event or occurance. The callable must take the object and the user and return a boolean.

example:

check_edit_permission(ob, user):
    return user.is_authenticated()

If ob is None, then the function is checking for permission to add new occurrences.

GET_EVENTS_FUNC

This setting controls the callable that gets all events for calendar display. The callable must take the request and the calendar and return a QuerySet of events. Modifying this setting allows you to pull events from multiple calendars or to filter events based on permissions

example:

get_events(request, calendar):
    return calendar.event_set.all()

Indices and tables