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', ' ') 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)) |