Archive for the ‘calendar’ Category

Django event calendar

One of the modules for e-cidadania project was a basic event calendar, meaning that the event will be marked on the respective modules (proposals, spaces, debates, etc.) and will be gathered by the calendar module. In the first moment i thought to use jquery directly, but after some research I found that it was easier to generate the calendar locally and serve it to the client, so here it is, a multilanguage, event-driven HTML calendar:

The basic explanation is that we create a class inheriting the LocaleHTMLCalendar (a localized version of the HTMLCalendar module) and override some functions like formatmonth() then in the view we stablish the current user locale, some basic protection (month number) and convert the month and year numbers to integers, since they come as strings from the URL.

models.py (I put it on models for convenience but it really should be on views.py)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import calendar
from datetime import date
from itertools import groupby
 
from django.utils.html import conditional_escape as esc
 
class EventCalendar(calendar.LocaleHTMLCalendar):
 
    """
    Event calendar is a basic calendar made with HTMLCalendar module.
    """
    def __init__(self, events, *args, **kwargs):
        self.events = self.group_by_day(events)
        super(EventCalendar, self).__init__(*args, **kwargs)
 
    def formatday(self, day, weekday):
        if day != 0:
            cssclass = self.cssclasses[weekday]
            if date.today() == date(self.year, self.month, day):
                cssclass += ' today'
            if day in self.events:
                cssclass += ' filled'
                body = ['<ul>']
                for event in self.events[day]:
                    body.append('<li>')
                    body.append('<a href="%s">' % event.get_absolute_url())
                    body.append(esc(event.title))
                    body.append('</a></li>')
                body.append('<ul>')
                return self.day_cell(cssclass, '%d %s' % (day, ''.join(body)))
            return self.day_cell(cssclass, day)
        return self.day_cell('noday', '&nbsp;')
 
    def formatmonth(self, year, month):
        self.year, self.month = year, month
        return super(EventCalendar, self).formatmonth(year, month)
 
    def group_by_day(self, events):
        field = lambda event: event.meeting_date.day
        return dict(
            [(day, list(items)) for day, items in groupby(events, field)]
        )
 
    def day_cell(self, cssclass, body):
        return '<td class="%s">%s</td>' % (cssclass, body)

views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from django.shortcuts import render_to_response, get_object_or_404
from django.utils.safestring import mark_safe
from django.template import RequestContext
from django.utils import translation
 
from e_cidadania.apps.spaces.models import Meeting, Space
from e_cidadania.apps.cal.models import EventCalendar
from e_cidadania import settings
 
def calendar(request, space_name, year, month):
 
    # Avoid people writing wrong numbers or any program errors.
    if int(month) not in range(1, 13):
        return render_to_response('cal/error.html',
                                  context_instance=RequestContext(request))
 
    place = get_object_or_404(Space, url=space_name)
    next_month = int(month) + 1
    prev_month = int(month) - 1
 
    meetings = Meeting.objects.order_by('meeting_date') \
                              .filter(space = place,
                                      meeting_date__year = year,
                                      meeting_date__month = month)
 
    cur_lang = translation.get_language()
    cur_locale = translation.to_locale(cur_lang)+'.UTF-8' #default encoding with django
    cal = EventCalendar(meetings, settings.FIRST_WEEK_DAY, cur_locale).formatmonth(int(year), int(month))
 
    return render_to_response('cal/calendar.html',
                              {'calendar': mark_safe(cal),
                               'nextmonth': '%02d' % next_month,
                               'prevmonth': '%02d' % prev_month,
                               'get_place': place},
                               context_instance = RequestContext(request))