06Oct

Generating ICalendar ICS files from Django-Events

Posted by Elf Sternberg as django, python

The Django Event Calendar is a fairly old and well-respected piece of code, useful for a variety of social networking and announcement-oriented applications.  It’s not the be-all of events calendars, but it does what it has to well enough.  I’ve used it on several projects.

The ${BOSS} asked me to use it for announcing upcoming movie showings, and she wanted me to add the capability to automatically export to Outlook or Google Calendar.   There is a python module for generating iCalendar files, and uniting the two is relatively straightforward. The only trick to making the iCalendar component work with Django is that both have a model named “Event”. Getting around this is a little awkward, but it can be managed with the magic of the django’s get_model() function.

This view handler uses the Site application for its event calendar information. I’ve named the file ics_views.py‘ and put it in the application folder projectname_events a django application where my application’s extensions to the events calendar are kept. Since I already have a views file there which imports events.Event, this was my way of keeping the two Event models apart. I’m sure my readers could come up with a more clever UUID generator than the one I’ve supplied below, but it is consistent and correct:

<ics_views.py>=
from datetime import datetime
from icalendar import Calendar, Event
from django.db.models import get_model
from django.http import HttpResponse
from django.contrib.sites.models import Site

def export(request, event_id):
    event = get_model('events', 'event').objects.get(id = event_id)

    cal = Calendar()
    site = Site.objects.get_current()

    cal.add('prodid', '-//%s Events Calendar//%s//' % (site.name, site.domain))
    cal.add('version', '2.0')

    site_token = site.domain.split('.')
    site_token.reverse()
    site_token = '.'.join(site_token)

    ical_event = Event()
    ical_event.add('summary', event.description)
    ical_event.add('dtstart', event.start)
    ical_event.add('dtend', event.end and event.end or event.start)
    ical_event.add('dtstamp', event.end and event.end or event.start)
    ical_event['uid'] = '%d.event.events.%s' % (event.id, site_token)
    cal.add_component(ical_event)

    response = HttpResponse(cal.as_string(), mimetype="text/calendar")
    response['Content-Disposition'] = 'attachment; filename=%s.ics' % event.slug
    return response

Now modify the project’s urls.py to include this object:

<urls.py>=
urlpatterns += patterns('',
    url(r'^events/(?P<event_id>\d+)/export/', 'app_events.ics_views.export', name="event_ics_export"),
)

And this can be invoked quite simply:

<events.html>=
...
<a href="{% url event_ics_export event.id %}" >Export Event</a></p>
...

And that’s all there is to it.  Now, when you click on the link above, you’ll be prompted to download an ICS file that, if your operating system appreciates such things, will automagically try and add it to your calendar.

2 Responses to Generating ICalendar ICS files from Django-Events

Issac Kelly

October 7th, 2010 at 6:28 am

Couldn’t this be helped with the from X import Y as Z pattern?

I looked up the
http://www.python.org/dev/peps/pep-0221/

Elf Sternberg

October 7th, 2010 at 7:54 am

Actually, I’m sure it could be. I’m not fond of the pattern because it obscures the origin of the class, and the get_model() technique is actually a recommended means of getting around issues like this.

Comment Form

Recent Comments