Exposing calendar events using iCalendar in Django

Posted by Christian on Mar 06 2008, 20:50 CEST
Tagged with Python, Django

I recently wrote simple abstraction for exposing calendar events in Django as iCalendar feeds. It relies on vobject for managing the formatting of the calendar file, so you will need this if you want to try it out. It is available in Debian in the python-vobject package.

Save this as a file somewhere in your project:

import vobject

from django.http import HttpResponse

EVENT_ITEMS = (
    ('uid', 'uid'),
    ('dtstart', 'start'),
    ('dtend', 'end'),
    ('summary', 'summary'),
    ('location', 'location'),
    ('last_modified', 'last_modified'),
    ('created', 'created'),
)

class ICalendarFeed(object):

    def __call__(self, *args, **kwargs):

        cal = vobject.iCalendar()

        for item in self.items():

            event = cal.add('vevent')

            for vkey, key in EVENT_ITEMS:
                value = getattr(self, 'item_' + key)(item)
                if value:
                    event.add(vkey).value = value

        response = HttpResponse(cal.serialize())
        response['Content-Type'] = 'text/calendar'

        return response

    def items(self):
        return []

    def item_uid(self, item):
        pass

    def item_start(self, item):
        pass

    def item_end(self, item):
        pass

    def item_summary(self, item):
        return str(item)

    def item_location(self, item):
        pass

    def item_last_modified(self, item):
        pass

    def item_created(self, item):
        pass

Now we need to couple this abstraction with a Django queryset. I placed this in a feeds.py in my application:

from yourproject.path.icalendar import ICalendarFeed
from yourproject.yourapp.models import SomeEvent

class SomeEventCalendar(ICalendarFeed):

    def items(self):
        return SomeEvent.objects.all()

    def item_uid(self, item):
        return str(item.id)

    def item_start(self, item):
        return item.start

    def item_end(self, item):
        return item.end

Finally we just need to put it somewhere in the urls.py:

from yourproject.yourapp.feeds import SomeEventCalendar

[...]

    (r'^feeds/icalendar/someevent/$', SomeEventCalendar()),

[...]

That's it.

Implementation notes

  • Start and end timestamps can be datetime.datetime objects (django.db.models.DateTimeField) as well as datetime.date objects (django.db.models.DateField). If they are datetime.date objects, the event will be exposed as an all-day event.
  • (Obviously) The methods you can override are listed in the ICalendarFeed class.
  • If you do not override the item_summary method, the __str__ representation of your model is used.

Comments for "Exposing calendar events using iCalendar in Django"

Currently disabled.