diff --git a/events/feeds.py b/events/feeds.py index 688f41e..3c11b29 100644 --- a/events/feeds.py +++ b/events/feeds.py @@ -46,10 +46,13 @@ class EventsFeed(BaseFeed): title = u"%s: events calendar." % current_site.name def link(self): - return reverse('events_index') + "?utm_source=feedreader&utm_medium=feed&utm_campaign=EventsFeed" + return reverse('events_index') def items(self): - return Event.objects.published()[:10] + return Event.objects.upcoming()[:10] def item_link(self, item): - return item.get_absolute_url() + "?utm_source=feedreader&utm_medium=feed&utm_campaign=EventsFeed" \ No newline at end of file + return item.get_absolute_url() + + def item_enclosure_url(self, item): + return "http://%s%s" % (current_site.domain, item.get_ical_url()) \ No newline at end of file diff --git a/events/models.py b/events/models.py index 78efa0f..f301628 100644 --- a/events/models.py +++ b/events/models.py @@ -76,6 +76,15 @@ def get_absolute_url(self): 'day': self.start_date.day, }) + @permalink + def get_ical_url(self): + return ('events_event_detail_ical', None, { + 'slug': self.slug, + 'year': self.start_date.year, + 'month': self.start_date.strftime('%b').lower(), + 'day': self.start_date.day, + }) + @property def start_datetime(self): if self.start_time: diff --git a/events/templates/events/tag_detail.html b/events/templates/events/tag_detail.html new file mode 100644 index 0000000..2aed29a --- /dev/null +++ b/events/templates/events/tag_detail.html @@ -0,0 +1,37 @@ +{% extends "events/base_events.html" %} + +{% block title %}{{ block.super }}: Events Tag {{ tag }}{% endblock %} + +{% block content_title %} +

Events Tag {{ tag }}

+{% endblock %} + +{% block content %} + + + {% if has_other_pages %} + + {% endif %} +{% endblock %} \ No newline at end of file diff --git a/events/templates/events/tag_list.html b/events/templates/events/tag_list.html new file mode 100644 index 0000000..6485113 --- /dev/null +++ b/events/templates/events/tag_list.html @@ -0,0 +1,15 @@ +{% extends "events/base_events.html" %} + +{% block title %}{{ block.super }}: Calendar Tags{% endblock %} + +{% block content_title %} +

Calendar Tags

+{% endblock %} + +{% block content %} + +{% endblock %} \ No newline at end of file diff --git a/events/urls.py b/events/urls.py index c9bf998..5dec10b 100644 --- a/events/urls.py +++ b/events/urls.py @@ -10,6 +10,10 @@ ) urlpatterns += patterns('events.views', + url(r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/(?P[-\w]+)/ical/$', + view = 'detail_ical', + name = 'events_event_detail_ical', + ), url(r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/(?P[-\w]+)/$', view = 'detail', name = 'events_event_detail', @@ -30,6 +34,26 @@ view = 'events_year', name = 'events_year', ), + url(r'^tag/(?P(.*))/page/(?P\d+)/$', + view = 'tag_detail', + name = 'events_tag_detail_paginated', + ), + url(r'^tag/(?P(.*))/ical/$', + view = 'tag_detail_ical', + name = 'events_tag_detail', + ), + url(r'^tag/(?P(.*))/$', + view = 'tag_detail', + name = 'events_tag_detail', + ), + url(r'^tag/$', + view = 'tag_list', + name = 'events_tag_list' + ), + url(r'^ical/$', + view = 'ical', + name = 'events_ical', + ), url(r'^archive/$', view = 'events_archives', name = 'events_archives' diff --git a/events/utils.py b/events/utils.py new file mode 100644 index 0000000..a0bb8ad --- /dev/null +++ b/events/utils.py @@ -0,0 +1,29 @@ +from icalendar import Calendar, Event, vText, vUri + +from django.contrib.sites.models import Site + +def export_ical(events): + 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) + + for event in events: + ical_event = Event() + ical_event.add('summary', event.title) + ical_event.add('description', event.body) + ical_event.add('dtstart', event.start_datetime) + ical_event.add('dtend', event.end_datetime) + ical_event.add('dtstamp', event.end_datetime) + ical_event.add('url', vUri('http://' + site.domain + event.get_absolute_url())) + ical_event['location'] = vText(event.location) + ical_event['uid'] = '%d.event.events.%s' % (event.id, site_token) + cal.add_component(ical_event) + + return cal \ No newline at end of file diff --git a/events/views.py b/events/views.py index c29c8ba..fe6dcc3 100644 --- a/events/views.py +++ b/events/views.py @@ -1,12 +1,14 @@ import datetime import time -from django.http import Http404, HttpResponse from django.template import RequestContext +from django.http import Http404, HttpResponse from django.shortcuts import render_to_response +from django.core.paginator import Paginator, InvalidPage, EmptyPage from events.models import Event from events.forms import CalendarYearMonthForm +from events.utils import export_ical def events_month(request, year=None, month=None): if not year: @@ -290,4 +292,78 @@ def detail(request, year, month, day, slug): except IndexError: raise Http404 - return render_to_response('events/detail.html', { 'event': event, 'date': date }, context_instance=RequestContext(request)) \ No newline at end of file + return render_to_response('events/detail.html', { 'event': event, 'date': date }, context_instance=RequestContext(request)) + +def detail_ical(request, year, month, day, slug): + try: + date = datetime.date(*time.strptime(year+month+day, '%Y%b%d')[:3]) + except ValueError: + raise Http404 + + try: + event = Event.objects.get(start_date=date, slug__iexact=slug) + except IndexError: + raise Http404 + + icalendar = export_ical([event, ]) + + response = HttpResponse(icalendar.as_string(), mimetype="text/calendar") + response['Content-Disposition'] = 'attachment: filename=%s-%s.ics' % (event.start_date.isoformat(), event.slug) + + return response + +def ical(request): + TODAY = datetime.date.today() + THRIDY_DAYS = datetime.timedelta(days=30) + + FUTURE = TODAY + THRIDY_DAYS + PAST = TODAY - THRIDY_DAYS + + event_list = Event.objects.filter(start_date__lte=FUTURE, start_date__gte=PAST) + + icalendar = export_ical(event_list) + + response = HttpResponse(icalendar.as_string(), mimetype="text/calendar") + response['Content-Disposition'] = 'attachment: filename=%s-%s.ics' % (FUTURE.isoformat(), PAST.isoformat()) + + return response + +def tag_list(request): + tags = Event.tags.all() + + context = { + 'tags': tags, + 'is_archive': True + } + + return render_to_response('events/tag_list.html', context, context_instance=RequestContext(request)) + +def tag_detail(request, slug, page=1): + tag = Event.tags.get(slug=slug) + event_list = Event.objects.filter(tags__in=[tag]) + + paginator = Paginator(event_list, 10) + + try: + events = paginator.page(page) + except (EmptyPage, InvalidPage): + events = paginator.page(paginator.num_pages) + + context = { + 'tag': tag, + 'events': events, + 'is_archive': True + } + + return render_to_response('events/tag_detail.html', context, context_instance=RequestContext(request)) + +def tag_detail_ical(request, slug): + tag = Event.tags.get(slug=slug) + event_list = Event.objects.upcoming(tags__in=[tag])[:10] + + icalendar = export_ical(event_list) + + response = HttpResponse(icalendar.as_string(), mimetype="text/calendar") + response['Content-Disposition'] = 'attachment: filename=%s.ics' % slug + + return response \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 9374e51..ce0bb62 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ python-dateutil django-taggit -django-markup \ No newline at end of file +django-markup +icalendar \ No newline at end of file