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 %}
+
+ {% for event in events.object_list %}
+ - {{ event }}
+ {% endfor %}
+
+
+ {% 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