--- /dev/null
+from django.contrib import admin
+from philo.admin import EntityAdmin, COLLAPSE_CLASSES
+from philo.contrib.julian.models import Location, Event, Calendar, CalendarView
+
+
+class LocationAdmin(EntityAdmin):
+ pass
+
+
+class EventAdmin(EntityAdmin):
+ fieldsets = (
+ (None, {
+ 'fields': ('name', 'slug', 'description', 'tags', 'owner')
+ }),
+ ('Location', {
+ 'fields': ('location_content_type', 'location_pk')
+ }),
+ ('Time', {
+ 'fields': (('start_date', 'start_time'), ('end_date', 'end_time'),),
+ }),
+ ('Advanced', {
+ 'fields': ('parent_event', 'uuid',),
+ 'classes': COLLAPSE_CLASSES
+ })
+ )
+ filter_horizontal = ['tags']
+ raw_id_fields = ['parent_event']
+ related_lookup_fields = {
+ 'fk': raw_id_fields,
+ 'generic': [["location_content_type", "location_pk"]]
+ }
+ prepopulated_fields = {'slug': ('name',)}
+
+
+class CalendarAdmin(EntityAdmin):
+ prepopulated_fields = {'slug': ('name',)}
+ filter_horizontal = ['events']
+ fieldsets = (
+ (None, {
+ 'fields': ('name', 'description', 'events')
+ }),
+ ('Advanced', {
+ 'fields': ('slug', 'uuid'),
+ 'classes': COLLAPSE_CLASSES
+ })
+ )
+
+
+class CalendarViewAdmin(EntityAdmin):
+ fieldsets = (
+ (None, {
+ 'fields': ('calendar',)
+ }),
+ ('Pages', {
+ 'fields': ('index_page', 'event_detail_page')
+ }),
+ ('General Settings', {
+ 'fields': ('tag_permalink_base', 'owner_permalink_base', 'location_permalink_base', 'events_per_page')
+ }),
+ ('Event List Pages', {
+ 'fields': ('timespan_page', 'tag_page', 'location_page', 'owner_page'),
+ 'classes': COLLAPSE_CLASSES
+ }),
+ ('Archive Pages', {
+ 'fields': ('location_archive_page', 'tag_archive_page', 'owner_archive_page'),
+ 'classes': COLLAPSE_CLASSES
+ }),
+ ('Feed Settings', {
+ 'fields': ( 'feeds_enabled', 'feed_suffix', 'feed_type', 'item_title_template', 'item_description_template',),
+ 'classes': COLLAPSE_CLASSES
+ })
+ )
+
+
+admin.site.register(Location, LocationAdmin)
+admin.site.register(Event, EventAdmin)
+admin.site.register(Calendar, CalendarAdmin)
+admin.site.register(CalendarView, CalendarViewAdmin)
\ No newline at end of file
--- /dev/null
+from django.http import HttpResponse
+from django.utils.feedgenerator import SyndicationFeed
+import vobject
+
+
+# Map the keys in the ICalendarFeed internal dictionary to the names of iCalendar attributes.
+FEED_ICAL_MAP = {
+ 'title': 'x-wr-calname',
+ 'description': 'x-wr-caldesc',
+ #'link': ???,
+ #'language': ???,
+ #author_email
+ #author_name
+ #author_link
+ #subtitle
+ #categories
+ #feed_url
+ #feed_copyright
+ 'id': 'prodid',
+ 'ttl': 'x-published-ttl'
+}
+
+
+ITEM_ICAL_MAP = {
+ 'title': 'summary',
+ 'description': 'description',
+ 'link': 'url',
+ # author_email, author_name, and author_link need special handling. Consider them the
+ # 'organizer' of the event <http://tools.ietf.org/html/rfc5545#section-3.8.4.3> and
+ # construct something based on that.
+ 'pubdate': 'created',
+ 'last_modified': 'last-modified',
+ #'comments' require special handling as well <http://tools.ietf.org/html/rfc5545#section-3.8.1.4>
+ 'unique_id': 'uid',
+ 'enclosure': 'attach', # does this need special handling?
+ 'categories': 'categories', # does this need special handling?
+ # ttl is ignored.
+ 'start': 'dtstart',
+ 'end': 'dtend',
+}
+
+
+class ICalendarFeed(SyndicationFeed):
+ #def __init__(self, title, link, description, language=None, author_email=None,
+ # author_name=None, author_link=None, subtitle=None, categories=None,
+ # feed_url=None, feed_copyright=None, feed_guid=None, ttl=None, **kwargs):
+ # super(ICalendarFeed, self).__init__(title, link, description, language,
+ # author_email, author_name, author_link, subtitle, categories,
+ # feed_url, feed_copyright, feed_guid, ttl, **kwargs)
+ #
+ mime_type = 'text/calendar'
+
+ def add_item(self, *args, **kwargs):
+ for kwarg in ['start', 'end', 'last_modified', 'location']:
+ kwargs.setdefault(kwarg, None)
+ super(ICalendarFeed, self).add_item(*args, **kwargs)
+
+ def write(self, outfile, encoding):
+ # TODO: Use encoding... how? Just convert all values when setting them should work...
+ cal = vobject.iCalendar()
+
+ # IE/Outlook needs this. See
+ # <http://blog.thescoop.org/archives/2007/07/31/django-ical-and-vobject/>
+ cal.add('method').value = 'PUBLISH'
+
+ for key, val in self.feed.items():
+ if key in FEED_ICAL_MAP and val:
+ cal.add(FEED_ICAL_MAP[key]).value = val
+
+ for item in self.items:
+ # TODO: handle multiple types of events.
+ event = cal.add('vevent')
+ for key, val in item.items():
+ #TODO: handle the non-standard items like comments and author.
+ if key in ITEM_ICAL_MAP and val:
+ event.add(ITEM_ICAL_MAP[key]).value = val
+
+ cal.serialize(outfile)
+
+ # Some special handling for HttpResponses. See link above.
+ if isinstance(outfile, HttpResponse):
+ filename = self.feed.get('filename', 'filename.ics')
+ outfile['Filename'] = filename
+ outfile['Content-Disposition'] = 'attachment; filename=%s' % filename
\ No newline at end of file
--- /dev/null
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding model 'Location'
+ db.create_table('julian_location', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ))
+ db.send_create_signal('julian', ['Location'])
+
+ # Adding model 'Event'
+ db.create_table('julian_event', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('start_date', self.gf('django.db.models.fields.DateField')()),
+ ('start_time', self.gf('django.db.models.fields.TimeField')(null=True, blank=True)),
+ ('end_date', self.gf('django.db.models.fields.DateField')()),
+ ('end_time', self.gf('django.db.models.fields.TimeField')(null=True, blank=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(max_length=255, db_index=True)),
+ ('location_content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),
+ ('location_pk', self.gf('django.db.models.fields.TextField')()),
+ ('description', self.gf('philo.models.fields.TemplateField')()),
+ ('parent_event', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['julian.Event'], null=True, blank=True)),
+ ('owner', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
+ ))
+ db.send_create_signal('julian', ['Event'])
+
+ # Adding M2M table for field tags on 'Event'
+ db.create_table('julian_event_tags', (
+ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+ ('event', models.ForeignKey(orm['julian.event'], null=False)),
+ ('tag', models.ForeignKey(orm['philo.tag'], null=False))
+ ))
+ db.create_unique('julian_event_tags', ['event_id', 'tag_id'])
+
+ # Adding model 'Calendar'
+ db.create_table('julian_calendar', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('uuid', self.gf('django.db.models.fields.CharField')(unique=True, max_length=100)),
+ ))
+ db.send_create_signal('julian', ['Calendar'])
+
+ # Adding M2M table for field events on 'Calendar'
+ db.create_table('julian_calendar_events', (
+ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+ ('calendar', models.ForeignKey(orm['julian.calendar'], null=False)),
+ ('event', models.ForeignKey(orm['julian.event'], null=False))
+ ))
+ db.create_unique('julian_calendar_events', ['calendar_id', 'event_id'])
+
+
+ def backwards(self, orm):
+
+ # Deleting model 'Location'
+ db.delete_table('julian_location')
+
+ # Deleting model 'Event'
+ db.delete_table('julian_event')
+
+ # Removing M2M table for field tags on 'Event'
+ db.delete_table('julian_event_tags')
+
+ # Deleting model 'Calendar'
+ db.delete_table('julian_calendar')
+
+ # Removing M2M table for field events on 'Calendar'
+ db.delete_table('julian_calendar_events')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'julian.calendar': {
+ 'Meta': {'object_name': 'Calendar'},
+ 'events': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'calendars'", 'symmetrical': 'False', 'to': "orm['julian.Event']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
+ },
+ 'julian.event': {
+ 'Meta': {'object_name': 'Event'},
+ 'description': ('philo.models.fields.TemplateField', [], {}),
+ 'end_date': ('django.db.models.fields.DateField', [], {}),
+ 'end_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'location_content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'location_pk': ('django.db.models.fields.TextField', [], {}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'parent_event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Event']", 'null': 'True', 'blank': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'start_date': ('django.db.models.fields.DateField', [], {}),
+ 'start_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['philo.Tag']", 'null': 'True', 'blank': 'True'})
+ },
+ 'julian.location': {
+ 'Meta': {'object_name': 'Location'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'philo.attribute': {
+ 'Meta': {'unique_together': "(('key', 'entity_content_type', 'entity_object_id'), ('value_content_type', 'value_object_id'))", 'object_name': 'Attribute'},
+ 'entity_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_entity_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'entity_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'value_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attribute_value_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
+ 'value_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'})
+ },
+ 'philo.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'})
+ }
+ }
+
+ complete_apps = ['julian']
--- /dev/null
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding field 'Event.created'
+ db.add_column('julian_event', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2011, 2, 10, 15, 14, 35, 721341), blank=True), keep_default=False)
+
+ # Adding field 'Event.last_modified'
+ db.add_column('julian_event', 'last_modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, default=datetime.datetime(2011, 2, 10, 15, 14, 42, 370147), blank=True), keep_default=False)
+
+ # Adding field 'Event.uuid'
+ db.add_column('julian_event', 'uuid', self.gf('django.db.models.fields.TextField')(default=''), keep_default=False)
+
+ # Adding field 'Calendar.slug'
+ db.add_column('julian_calendar', 'slug', self.gf('django.db.models.fields.SlugField')(default='', max_length=100, db_index=True), keep_default=False)
+
+ # Adding field 'Calendar.description'
+ db.add_column('julian_calendar', 'description', self.gf('django.db.models.fields.TextField')(default='', blank=True), keep_default=False)
+
+ # Changing field 'Calendar.uuid'
+ db.alter_column('julian_calendar', 'uuid', self.gf('django.db.models.fields.TextField')(unique=True))
+
+
+ def backwards(self, orm):
+
+ # Deleting field 'Event.created'
+ db.delete_column('julian_event', 'created')
+
+ # Deleting field 'Event.last_modified'
+ db.delete_column('julian_event', 'last_modified')
+
+ # Deleting field 'Event.uuid'
+ db.delete_column('julian_event', 'uuid')
+
+ # Deleting field 'Calendar.slug'
+ db.delete_column('julian_calendar', 'slug')
+
+ # Deleting field 'Calendar.description'
+ db.delete_column('julian_calendar', 'description')
+
+ # Changing field 'Calendar.uuid'
+ db.alter_column('julian_calendar', 'uuid', self.gf('django.db.models.fields.CharField')(max_length=100, unique=True))
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'julian.calendar': {
+ 'Meta': {'object_name': 'Calendar'},
+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'events': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'calendars'", 'symmetrical': 'False', 'to': "orm['julian.Event']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'db_index': 'True'}),
+ 'uuid': ('django.db.models.fields.TextField', [], {'unique': 'True'})
+ },
+ 'julian.event': {
+ 'Meta': {'object_name': 'Event'},
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'description': ('philo.models.fields.TemplateField', [], {}),
+ 'end_date': ('django.db.models.fields.DateField', [], {}),
+ 'end_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'location_content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'location_pk': ('django.db.models.fields.TextField', [], {}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'parent_event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Event']", 'null': 'True', 'blank': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'start_date': ('django.db.models.fields.DateField', [], {}),
+ 'start_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['philo.Tag']", 'null': 'True', 'blank': 'True'}),
+ 'uuid': ('django.db.models.fields.TextField', [], {})
+ },
+ 'julian.location': {
+ 'Meta': {'object_name': 'Location'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'philo.attribute': {
+ 'Meta': {'unique_together': "(('key', 'entity_content_type', 'entity_object_id'), ('value_content_type', 'value_object_id'))", 'object_name': 'Attribute'},
+ 'entity_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_entity_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'entity_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'value_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attribute_value_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
+ 'value_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'})
+ },
+ 'philo.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'})
+ }
+ }
+
+ complete_apps = ['julian']
--- /dev/null
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding model 'ICalendarFeedView'
+ db.create_table('julian_icalendarfeedview', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('feed_type', self.gf('django.db.models.fields.CharField')(default='application/atom+xml', max_length=50)),
+ ('feed_suffix', self.gf('django.db.models.fields.CharField')(default='feed', max_length=255)),
+ ('feeds_enabled', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),
+ ('item_title_template', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='julian_icalendarfeedview_title_related', null=True, to=orm['philo.Template'])),
+ ('item_description_template', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='julian_icalendarfeedview_description_related', null=True, to=orm['philo.Template'])),
+ ('calendar', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['julian.Calendar'])),
+ ))
+ db.send_create_signal('julian', ['ICalendarFeedView'])
+
+
+ def backwards(self, orm):
+
+ # Deleting model 'ICalendarFeedView'
+ db.delete_table('julian_icalendarfeedview')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'julian.calendar': {
+ 'Meta': {'object_name': 'Calendar'},
+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'events': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'calendars'", 'symmetrical': 'False', 'to': "orm['julian.Event']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'db_index': 'True'}),
+ 'uuid': ('django.db.models.fields.TextField', [], {'unique': 'True'})
+ },
+ 'julian.event': {
+ 'Meta': {'object_name': 'Event'},
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'description': ('philo.models.fields.TemplateField', [], {}),
+ 'end_date': ('django.db.models.fields.DateField', [], {}),
+ 'end_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'location_content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'location_pk': ('django.db.models.fields.TextField', [], {}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'parent_event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Event']", 'null': 'True', 'blank': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'start_date': ('django.db.models.fields.DateField', [], {}),
+ 'start_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['philo.Tag']", 'null': 'True', 'blank': 'True'}),
+ 'uuid': ('django.db.models.fields.TextField', [], {})
+ },
+ 'julian.icalendarfeedview': {
+ 'Meta': {'object_name': 'ICalendarFeedView'},
+ 'calendar': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Calendar']"}),
+ 'feed_suffix': ('django.db.models.fields.CharField', [], {'default': "'feed'", 'max_length': '255'}),
+ 'feed_type': ('django.db.models.fields.CharField', [], {'default': "'application/atom+xml'", 'max_length': '50'}),
+ 'feeds_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'item_description_template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'julian_icalendarfeedview_description_related'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'item_title_template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'julian_icalendarfeedview_title_related'", 'null': 'True', 'to': "orm['philo.Template']"})
+ },
+ 'julian.location': {
+ 'Meta': {'object_name': 'Location'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'philo.attribute': {
+ 'Meta': {'unique_together': "(('key', 'entity_content_type', 'entity_object_id'), ('value_content_type', 'value_object_id'))", 'object_name': 'Attribute'},
+ 'entity_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_entity_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'entity_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'value_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attribute_value_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
+ 'value_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'})
+ },
+ 'philo.node': {
+ 'Meta': {'object_name': 'Node'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['philo.Node']"}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'view_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'node_view_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'view_object_id': ('django.db.models.fields.PositiveIntegerField', [], {})
+ },
+ 'philo.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'})
+ },
+ 'philo.template': {
+ 'Meta': {'object_name': 'Template'},
+ 'code': ('philo.models.fields.TemplateField', [], {}),
+ 'documentation': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "'text/html'", 'max_length': '255'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+ }
+ }
+
+ complete_apps = ['julian']
--- /dev/null
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Changing field 'Event.location_content_type'
+ db.alter_column('julian_event', 'location_content_type_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'], null=True, blank=True))
+
+ # Changing field 'Event.location_pk'
+ db.alter_column('julian_event', 'location_pk', self.gf('django.db.models.fields.TextField')(blank=True))
+
+
+ def backwards(self, orm):
+
+ # Changing field 'Event.location_content_type'
+ db.alter_column('julian_event', 'location_content_type_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType']))
+
+ # Changing field 'Event.location_pk'
+ db.alter_column('julian_event', 'location_pk', self.gf('django.db.models.fields.TextField')())
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'julian.calendar': {
+ 'Meta': {'object_name': 'Calendar'},
+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'events': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'calendars'", 'symmetrical': 'False', 'to': "orm['julian.Event']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'db_index': 'True'}),
+ 'uuid': ('django.db.models.fields.TextField', [], {'unique': 'True'})
+ },
+ 'julian.event': {
+ 'Meta': {'object_name': 'Event'},
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'description': ('philo.models.fields.TemplateField', [], {}),
+ 'end_date': ('django.db.models.fields.DateField', [], {}),
+ 'end_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'location_content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
+ 'location_pk': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'parent_event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Event']", 'null': 'True', 'blank': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'start_date': ('django.db.models.fields.DateField', [], {}),
+ 'start_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['philo.Tag']", 'null': 'True', 'blank': 'True'}),
+ 'uuid': ('django.db.models.fields.TextField', [], {})
+ },
+ 'julian.icalendarfeedview': {
+ 'Meta': {'object_name': 'ICalendarFeedView'},
+ 'calendar': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Calendar']"}),
+ 'feed_suffix': ('django.db.models.fields.CharField', [], {'default': "'feed'", 'max_length': '255'}),
+ 'feed_type': ('django.db.models.fields.CharField', [], {'default': "'application/atom+xml'", 'max_length': '50'}),
+ 'feeds_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'item_description_template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'julian_icalendarfeedview_description_related'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'item_title_template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'julian_icalendarfeedview_title_related'", 'null': 'True', 'to': "orm['philo.Template']"})
+ },
+ 'julian.location': {
+ 'Meta': {'object_name': 'Location'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'philo.attribute': {
+ 'Meta': {'unique_together': "(('key', 'entity_content_type', 'entity_object_id'), ('value_content_type', 'value_object_id'))", 'object_name': 'Attribute'},
+ 'entity_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_entity_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'entity_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'value_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attribute_value_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
+ 'value_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'})
+ },
+ 'philo.node': {
+ 'Meta': {'object_name': 'Node'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['philo.Node']"}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'view_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'node_view_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'view_object_id': ('django.db.models.fields.PositiveIntegerField', [], {})
+ },
+ 'philo.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'})
+ },
+ 'philo.template': {
+ 'Meta': {'object_name': 'Template'},
+ 'code': ('philo.models.fields.TemplateField', [], {}),
+ 'documentation': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "'text/html'", 'max_length': '255'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+ }
+ }
+
+ complete_apps = ['julian']
--- /dev/null
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Deleting model 'ICalendarFeedView'
+ db.delete_table('julian_icalendarfeedview')
+
+ # Adding model 'CalendarView'
+ db.create_table('julian_calendarview', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('feed_type', self.gf('django.db.models.fields.CharField')(default='text/calendar', max_length=50)),
+ ('feed_suffix', self.gf('django.db.models.fields.CharField')(default='feed', max_length=255)),
+ ('feeds_enabled', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),
+ ('item_title_template', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='julian_calendarview_title_related', null=True, to=orm['philo.Template'])),
+ ('item_description_template', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='julian_calendarview_description_related', null=True, to=orm['philo.Template'])),
+ ('calendar', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['julian.Calendar'])),
+ ('index_page', self.gf('django.db.models.fields.related.ForeignKey')(related_name='calendar_index_related', to=orm['philo.Page'])),
+ ('timespan_page', self.gf('django.db.models.fields.related.ForeignKey')(related_name='calendar_timespan_related', to=orm['philo.Page'])),
+ ('event_detail_page', self.gf('django.db.models.fields.related.ForeignKey')(related_name='calendar_detail_related', to=orm['philo.Page'])),
+ ('tag_page', self.gf('django.db.models.fields.related.ForeignKey')(related_name='calendar_tag_related', to=orm['philo.Page'])),
+ ('location_page', self.gf('django.db.models.fields.related.ForeignKey')(related_name='calendar_location_related', to=orm['philo.Page'])),
+ ('owner_page', self.gf('django.db.models.fields.related.ForeignKey')(related_name='calendar_owner_related', to=orm['philo.Page'])),
+ ('tag_archive_page', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='calendar_tag_archive_related', null=True, to=orm['philo.Page'])),
+ ('location_archive_page', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='calendar_location_archive_related', null=True, to=orm['philo.Page'])),
+ ('owner_archive_page', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='calendar_owner_archive_related', null=True, to=orm['philo.Page'])),
+ ('tag_permalink_base', self.gf('django.db.models.fields.CharField')(default='tags', max_length=30)),
+ ('owner_permalink_base', self.gf('django.db.models.fields.CharField')(default='owner', max_length=30)),
+ ('location_permalink_base', self.gf('django.db.models.fields.CharField')(default='location', max_length=30)),
+ ))
+ db.send_create_signal('julian', ['CalendarView'])
+
+ # Adding field 'Location.slug'
+ db.add_column('julian_location', 'slug', self.gf('django.db.models.fields.SlugField')(default='slug', unique=True, max_length=255, db_index=True), keep_default=False)
+
+
+ def backwards(self, orm):
+
+ # Adding model 'ICalendarFeedView'
+ db.create_table('julian_icalendarfeedview', (
+ ('item_title_template', self.gf('django.db.models.fields.related.ForeignKey')(related_name='julian_icalendarfeedview_title_related', null=True, to=orm['philo.Template'], blank=True)),
+ ('feed_type', self.gf('django.db.models.fields.CharField')(default='application/atom+xml', max_length=50)),
+ ('item_description_template', self.gf('django.db.models.fields.related.ForeignKey')(related_name='julian_icalendarfeedview_description_related', null=True, to=orm['philo.Template'], blank=True)),
+ ('feeds_enabled', self.gf('django.db.models.fields.BooleanField')(default=True, blank=True)),
+ ('calendar', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['julian.Calendar'])),
+ ('feed_suffix', self.gf('django.db.models.fields.CharField')(default='feed', max_length=255)),
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ))
+ db.send_create_signal('julian', ['ICalendarFeedView'])
+
+ # Deleting model 'CalendarView'
+ db.delete_table('julian_calendarview')
+
+ # Deleting field 'Location.slug'
+ db.delete_column('julian_location', 'slug')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'julian.calendar': {
+ 'Meta': {'object_name': 'Calendar'},
+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'events': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'calendars'", 'symmetrical': 'False', 'to': "orm['julian.Event']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'db_index': 'True'}),
+ 'uuid': ('django.db.models.fields.TextField', [], {'unique': 'True'})
+ },
+ 'julian.calendarview': {
+ 'Meta': {'object_name': 'CalendarView'},
+ 'calendar': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Calendar']"}),
+ 'event_detail_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'calendar_detail_related'", 'to': "orm['philo.Page']"}),
+ 'feed_suffix': ('django.db.models.fields.CharField', [], {'default': "'feed'", 'max_length': '255'}),
+ 'feed_type': ('django.db.models.fields.CharField', [], {'default': "'text/calendar'", 'max_length': '50'}),
+ 'feeds_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'index_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'calendar_index_related'", 'to': "orm['philo.Page']"}),
+ 'item_description_template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'julian_calendarview_description_related'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'item_title_template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'julian_calendarview_title_related'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'location_archive_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_location_archive_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'location_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'calendar_location_related'", 'to': "orm['philo.Page']"}),
+ 'location_permalink_base': ('django.db.models.fields.CharField', [], {'default': "'location'", 'max_length': '30'}),
+ 'owner_archive_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_owner_archive_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'owner_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'calendar_owner_related'", 'to': "orm['philo.Page']"}),
+ 'owner_permalink_base': ('django.db.models.fields.CharField', [], {'default': "'owner'", 'max_length': '30'}),
+ 'tag_archive_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_tag_archive_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'tag_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'calendar_tag_related'", 'to': "orm['philo.Page']"}),
+ 'tag_permalink_base': ('django.db.models.fields.CharField', [], {'default': "'tags'", 'max_length': '30'}),
+ 'timespan_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'calendar_timespan_related'", 'to': "orm['philo.Page']"})
+ },
+ 'julian.event': {
+ 'Meta': {'object_name': 'Event'},
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'description': ('philo.models.fields.TemplateField', [], {}),
+ 'end_date': ('django.db.models.fields.DateField', [], {}),
+ 'end_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'location_content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
+ 'location_pk': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'parent_event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Event']", 'null': 'True', 'blank': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'start_date': ('django.db.models.fields.DateField', [], {}),
+ 'start_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'events'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['philo.Tag']"}),
+ 'uuid': ('django.db.models.fields.TextField', [], {})
+ },
+ 'julian.location': {
+ 'Meta': {'object_name': 'Location'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'})
+ },
+ 'philo.attribute': {
+ 'Meta': {'unique_together': "(('key', 'entity_content_type', 'entity_object_id'), ('value_content_type', 'value_object_id'))", 'object_name': 'Attribute'},
+ 'entity_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_entity_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'entity_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'value_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attribute_value_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
+ 'value_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'})
+ },
+ 'philo.node': {
+ 'Meta': {'object_name': 'Node'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['philo.Node']"}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'view_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'node_view_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'view_object_id': ('django.db.models.fields.PositiveIntegerField', [], {})
+ },
+ 'philo.page': {
+ 'Meta': {'object_name': 'Page'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pages'", 'to': "orm['philo.Template']"}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'philo.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'})
+ },
+ 'philo.template': {
+ 'Meta': {'object_name': 'Template'},
+ 'code': ('philo.models.fields.TemplateField', [], {}),
+ 'documentation': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "'text/html'", 'max_length': '255'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+ }
+ }
+
+ complete_apps = ['julian']
--- /dev/null
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding field 'CalendarView.events_per_page'
+ db.add_column('julian_calendarview', 'events_per_page', self.gf('django.db.models.fields.PositiveIntegerField')(null=True, blank=True), keep_default=False)
+
+ # Changing field 'CalendarView.timespan_page'
+ db.alter_column('julian_calendarview', 'timespan_page_id', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, null=True, to=orm['philo.Page']))
+
+ # Changing field 'CalendarView.owner_page'
+ db.alter_column('julian_calendarview', 'owner_page_id', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, null=True, to=orm['philo.Page']))
+
+ # Changing field 'CalendarView.location_page'
+ db.alter_column('julian_calendarview', 'location_page_id', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, null=True, to=orm['philo.Page']))
+
+ # Changing field 'CalendarView.tag_page'
+ db.alter_column('julian_calendarview', 'tag_page_id', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, null=True, to=orm['philo.Page']))
+
+
+ def backwards(self, orm):
+
+ # Deleting field 'CalendarView.events_per_page'
+ db.delete_column('julian_calendarview', 'events_per_page')
+
+ # Changing field 'CalendarView.timespan_page'
+ db.alter_column('julian_calendarview', 'timespan_page_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['philo.Page']))
+
+ # Changing field 'CalendarView.owner_page'
+ db.alter_column('julian_calendarview', 'owner_page_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['philo.Page']))
+
+ # Changing field 'CalendarView.location_page'
+ db.alter_column('julian_calendarview', 'location_page_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['philo.Page']))
+
+ # Changing field 'CalendarView.tag_page'
+ db.alter_column('julian_calendarview', 'tag_page_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['philo.Page']))
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'julian.calendar': {
+ 'Meta': {'object_name': 'Calendar'},
+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'events': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'calendars'", 'symmetrical': 'False', 'to': "orm['julian.Event']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'db_index': 'True'}),
+ 'uuid': ('django.db.models.fields.TextField', [], {'unique': 'True'})
+ },
+ 'julian.calendarview': {
+ 'Meta': {'object_name': 'CalendarView'},
+ 'calendar': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Calendar']"}),
+ 'event_detail_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'calendar_detail_related'", 'to': "orm['philo.Page']"}),
+ 'events_per_page': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'feed_suffix': ('django.db.models.fields.CharField', [], {'default': "'feed'", 'max_length': '255'}),
+ 'feed_type': ('django.db.models.fields.CharField', [], {'default': "'text/calendar'", 'max_length': '50'}),
+ 'feeds_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'index_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'calendar_index_related'", 'to': "orm['philo.Page']"}),
+ 'item_description_template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'julian_calendarview_description_related'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'item_title_template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'julian_calendarview_title_related'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'location_archive_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_location_archive_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'location_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_location_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'location_permalink_base': ('django.db.models.fields.CharField', [], {'default': "'location'", 'max_length': '30'}),
+ 'owner_archive_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_owner_archive_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'owner_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_owner_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'owner_permalink_base': ('django.db.models.fields.CharField', [], {'default': "'owner'", 'max_length': '30'}),
+ 'tag_archive_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_tag_archive_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'tag_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_tag_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'tag_permalink_base': ('django.db.models.fields.CharField', [], {'default': "'tags'", 'max_length': '30'}),
+ 'timespan_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_timespan_related'", 'null': 'True', 'to': "orm['philo.Page']"})
+ },
+ 'julian.event': {
+ 'Meta': {'object_name': 'Event'},
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'description': ('philo.models.fields.TemplateField', [], {}),
+ 'end_date': ('django.db.models.fields.DateField', [], {}),
+ 'end_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'location_content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
+ 'location_pk': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'parent_event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Event']", 'null': 'True', 'blank': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'start_date': ('django.db.models.fields.DateField', [], {}),
+ 'start_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'events'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['philo.Tag']"}),
+ 'uuid': ('django.db.models.fields.TextField', [], {})
+ },
+ 'julian.location': {
+ 'Meta': {'object_name': 'Location'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'})
+ },
+ 'philo.attribute': {
+ 'Meta': {'unique_together': "(('key', 'entity_content_type', 'entity_object_id'), ('value_content_type', 'value_object_id'))", 'object_name': 'Attribute'},
+ 'entity_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_entity_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'entity_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'value_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attribute_value_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
+ 'value_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'})
+ },
+ 'philo.node': {
+ 'Meta': {'object_name': 'Node'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['philo.Node']"}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'view_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'node_view_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'view_object_id': ('django.db.models.fields.PositiveIntegerField', [], {})
+ },
+ 'philo.page': {
+ 'Meta': {'object_name': 'Page'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pages'", 'to': "orm['philo.Template']"}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'philo.tag': {
+ 'Meta': {'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'})
+ },
+ 'philo.template': {
+ 'Meta': {'object_name': 'Template'},
+ 'code': ('philo.models.fields.TemplateField', [], {}),
+ 'documentation': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "'text/html'", 'max_length': '255'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+ }
+ }
+
+ complete_apps = ['julian']
--- /dev/null
+from django.conf import settings
+from django.conf.urls.defaults import url, patterns, include
+from django.contrib.auth.models import User
+from django.contrib.contenttypes.generic import GenericForeignKey
+from django.contrib.contenttypes.models import ContentType
+from django.core.exceptions import ValidationError, ObjectDoesNotExist
+from django.core.validators import RegexValidator
+from django.db import models
+from django.http import HttpResponse, Http404
+from django.utils.encoding import force_unicode
+from philo.contrib.julian.feedgenerator import ICalendarFeed
+from philo.contrib.penfield.models import FeedView, FEEDS
+from philo.exceptions import ViewCanNotProvideSubpath
+from philo.models import Tag, Entity, Page, TemplateField
+from philo.utils import ContentTypeRegistryLimiter
+import re, datetime, calendar
+
+
+# TODO: Could this regex more closely match the Formal Public Identifier spec?
+# http://xml.coverpages.org/tauber-fpi.html
+FPI_REGEX = re.compile(r"(|\+//|-//)[^/]+//[^/]+//[A-Z]{2}")
+
+
+ICALENDAR = ICalendarFeed.mime_type
+FEEDS[ICALENDAR] = ICalendarFeed
+
+
+location_content_type_limiter = ContentTypeRegistryLimiter()
+
+
+def register_location_model(model):
+ location_content_type_limiter.register_class(model)
+
+
+def unregister_location_model(model):
+ location_content_type_limiter.unregister_class(model)
+
+
+class Location(Entity):
+ name = models.CharField(max_length=255)
+ slug = models.SlugField(max_length=255, unique=True)
+
+ def __unicode__(self):
+ return self.name
+
+
+register_location_model(Location)
+
+
+class TimedModel(models.Model):
+ start_date = models.DateField(help_text="YYYY-MM-DD")
+ start_time = models.TimeField(blank=True, null=True, help_text="HH:MM:SS - 24 hour clock")
+ end_date = models.DateField()
+ end_time = models.TimeField(blank=True, null=True)
+
+ def is_all_day(self):
+ return self.start_time is None and self.end_time is None
+
+ def clean(self):
+ if bool(self.start_time) != bool(self.end_time):
+ raise ValidationError("A %s must have either a start time and an end time or neither.")
+
+ if self.start_date > self.end_date or self.start_date == self.end_date and self.start_time > self.end_time:
+ raise ValidationError("A %s cannot end before it starts." % self.__class__.__name__)
+
+ def get_start(self):
+ return self.start_date
+
+ def get_end(self):
+ return self.end_date
+
+ class Meta:
+ abstract = True
+
+
+class Event(Entity, TimedModel):
+ name = models.CharField(max_length=255)
+ slug = models.SlugField(max_length=255, unique_for_date='start_date')
+
+ location_content_type = models.ForeignKey(ContentType, limit_choices_to=location_content_type_limiter, blank=True, null=True)
+ location_pk = models.TextField(blank=True)
+ location = GenericForeignKey('location_content_type', 'location_pk')
+
+ description = TemplateField()
+
+ tags = models.ManyToManyField(Tag, related_name='events', blank=True, null=True)
+
+ parent_event = models.ForeignKey('self', blank=True, null=True)
+
+ # TODO: "User module"
+ owner = models.ForeignKey(User, related_name='owned_events')
+
+ created = models.DateTimeField(auto_now_add=True)
+ last_modified = models.DateTimeField(auto_now=True)
+ uuid = models.TextField() # Format?
+
+ def __unicode__(self):
+ return self.name
+
+
+class Calendar(Entity):
+ name = models.CharField(max_length=100)
+ slug = models.SlugField(max_length=100)
+ description = models.TextField(blank=True)
+ events = models.ManyToManyField(Event, related_name='calendars')
+
+ # TODO: Can we auto-generate this on save based on site id and calendar name and settings language?
+ uuid = models.TextField("Calendar UUID", unique=True, help_text="Should conform to Formal Public Identifier format. See <a href='http://en.wikipedia.org/wiki/Formal_Public_Identifier'>Wikipedia</a>.", validators=[RegexValidator(FPI_REGEX)])
+
+ def __unicode__(self):
+ return self.name
+
+
+class CalendarView(FeedView):
+ calendar = models.ForeignKey(Calendar)
+ index_page = models.ForeignKey(Page, related_name="calendar_index_related")
+ event_detail_page = models.ForeignKey(Page, related_name="calendar_detail_related")
+
+ timespan_page = models.ForeignKey(Page, related_name="calendar_timespan_related", blank=True, null=True)
+ tag_page = models.ForeignKey(Page, related_name="calendar_tag_related", blank=True, null=True)
+ location_page = models.ForeignKey(Page, related_name="calendar_location_related", blank=True, null=True)
+ owner_page = models.ForeignKey(Page, related_name="calendar_owner_related", blank=True, null=True)
+
+ tag_archive_page = models.ForeignKey(Page, related_name="calendar_tag_archive_related", blank=True, null=True)
+ location_archive_page = models.ForeignKey(Page, related_name="calendar_location_archive_related", blank=True, null=True)
+ owner_archive_page = models.ForeignKey(Page, related_name="calendar_owner_archive_related", blank=True, null=True)
+
+ tag_permalink_base = models.CharField(max_length=30, default='tags')
+ owner_permalink_base = models.CharField(max_length=30, default='owners')
+ location_permalink_base = models.CharField(max_length=30, default='locations')
+ events_per_page = models.PositiveIntegerField(blank=True, null=True)
+
+ item_context_var = "events"
+ object_attr = "calendar"
+
+ def get_reverse_params(self, obj):
+ if isinstance(obj, User):
+ return 'events_for_user', [], {'username': obj.username}
+ elif isinstance(obj, Event):
+ return 'event_detail', [], {
+ 'year': str(obj.start_date.year).zfill(4),
+ 'month': str(obj.start_date.month).zfill(2),
+ 'day': str(obj.start_date.day).zfill(2),
+ 'slug': obj.slug
+ }
+ elif isinstance(obj, Tag) or isinstance(obj, models.query.QuerySet) and obj.model == Tag:
+ if isinstance(obj, Tag):
+ obj = [obj]
+ return 'entries_by_tag', [], {'tag_slugs': '/'.join(obj)}
+ raise ViewCanNotProvideSubpath
+
+ def timespan_patterns(self, timespan_name):
+ return self.feed_patterns('get_events_by_timespan', 'timespan_page', "events_by_%s" % timespan_name)
+
+ @property
+ def urlpatterns(self):
+ urlpatterns = patterns('',
+ url(r'^', include(self.feed_patterns('get_all_events', 'index_page', 'index'))),
+
+ url(r'^(?P<year>\d{4})', include(self.timespan_patterns('year'))),
+ url(r'^(?P<year>\d{4})/(?P<month>\d{2})', include(self.timespan_patterns('month'))),
+ url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})', include(self.timespan_patterns('day'))),
+ #url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<hour>\d{1,2})', include(self.timespan_patterns('hour'))),
+ url(r'(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<slug>[\w-]+)', self.event_detail_view, name="event_detail"),
+
+ url(r'^%s/(?P<username>[^/]+)' % self.owner_permalink_base, include(self.feed_patterns('get_events_by_owner', 'owner_page', 'events_by_user'))),
+
+ # Some sort of shortcut for a location would be useful. This could be on a per-calendar
+ # or per-calendar-view basis.
+ #url(r'^%s/(?P<slug>[\w-]+)' % self.location_permalink_base, ...)
+ url(r'^%s/(?P<app_label>\w+)/(?P<model>\w+)/(?P<pk>[^/]+)' % self.location_permalink_base, include(self.feed_patterns('get_events_by_location', 'location_page', 'events_by_location'))),
+ )
+
+ if self.feeds_enabled:
+ urlpatterns += patterns('',
+ url(r'^%s/(?P<tag_slugs>[-\w]+[-+/\w]*)/%s$' % (self.tag_permalink_base, self.feed_suffix), self.feed_view('get_events_by_tag', 'events_by_tag_feed'), name='events_by_tag_feed'),
+ )
+ urlpatterns += patterns('',
+ url(r'^%s/(?P<tag_slugs>[-\w]+[-+/\w]*)$' % self.tag_permalink_base, self.page_view('get_events_by_tag', 'tag_page'), name='events_by_tag')
+ )
+
+ if self.tag_archive_page:
+ urlpatterns += patterns('',
+ url(r'^%s$' % self.tag_permalink_base, self.tag_archive_view, name='tag_archive')
+ )
+
+ if self.owner_archive_page:
+ urlpatterns += patterns('',
+ url(r'^%s$' % self.owner_permalink_base, self.owner_archive_view, name='owner_archive')
+ )
+
+ if self.location_archive_page:
+ urlpatterns += patterns('',
+ url(r'^%s$' % self.location_permalink_base, self.location_archive_view, name='location_archive')
+ )
+ return urlpatterns
+
+ # Basic QuerySet fetchers.
+ def get_event_queryset(self):
+ return self.calendar.events.all()
+
+ def get_timespan_queryset(self, year, month=None, day=None):
+ qs = self.get_event_queryset()
+ # See python documentation for the min/max values.
+ if year and month and day:
+ year, month, day = int(year), int(month), int(day)
+ start_datetime = datetime.datetime(year, month, day, 0, 0)
+ end_datetime = datetime.datetime(year, month, day, 23, 59)
+ elif year and month:
+ year, month = int(year), int(month)
+ start_datetime = datetime.datetime(year, month, 1, 0, 0)
+ end_datetime = datetime.datetime(year, month, calendar.monthrange(year, month)[1], 23, 59)
+ else:
+ year = int(year)
+ start_datetime = datetime.datetime(year, 1, 1, 0, 0)
+ end_datetime = datetime.datetime(year, 12, 31, 23, 59)
+
+ return qs.exclude(end_date__lt=start_datetime, end_time__lt=start_datetime).exclude(start_date__gt=end_datetime, start_time__gt=end_datetime, start_time__isnull=False).exclude(start_time__isnull=True, start_date__gt=end_datetime)
+
+ def get_tag_queryset(self):
+ return Tag.objects.filter(events__calendars=self.calendar).distinct()
+
+ def get_location_querysets(self):
+ # Potential bottleneck?
+ location_map = {}
+ locations = Event.objects.values_list('location_content_type', 'location_pk')
+
+ for ct, pk in locations:
+ location_map.setdefault(ct, []).append(pk)
+
+ location_cts = ContentType.objects.in_bulk(location_map.keys())
+ location_querysets = {}
+
+ for ct_pk, pks in location_map.items():
+ ct = location_cts[ct_pk]
+ location_querysets[ct] = ct.model_class()._default_manager.filter(pk__in=pks)
+
+ return location_querysets
+
+ def get_owner_queryset(self):
+ return User.objects.filter(owned_events__calendars=self.calendar).distinct()
+
+ # Event QuerySet parsers for a request/args/kwargs
+ def get_all_events(self, request, extra_context=None):
+ return self.get_event_queryset(), extra_context
+
+ def get_events_by_timespan(self, request, year, month=None, day=None, extra_context=None):
+ context = extra_context or {}
+ context.update({
+ 'year': year,
+ 'month': month,
+ 'day': day
+ })
+ return self.get_timespan_queryset(year, month, day), context
+
+ def get_events_by_owner(self, request, username, extra_context=None):
+ try:
+ owner = self.get_owner_queryset().get(username=username)
+ except User.DoesNotExist:
+ raise Http404
+
+ qs = self.get_event_queryset().filter(owner=owner)
+ context = extra_context or {}
+ context.update({
+ 'owner': owner
+ })
+ return qs, context
+
+ def get_events_by_tag(self, request, tag_slugs, extra_context=None):
+ tag_slugs = tag_slugs.replace('+', '/').split('/')
+ tags = self.get_tag_queryset().filter(slug__in=tag_slugs)
+
+ if not tags:
+ raise Http404
+
+ # Raise a 404 on an incorrect slug.
+ found_slugs = [tag.slug for tag in tags]
+ for slug in tag_slugs:
+ if slug and slug not in found_slugs:
+ raise Http404
+
+ events = self.get_event_queryset()
+ for tag in tags:
+ events = events.filter(tags=tag)
+
+ context = extra_context or {}
+ context.update({'tags': tags})
+
+ return events, context
+
+ def get_events_by_location(self, request, app_label, model, pk, extra_context=None):
+ try:
+ ct = ContentType.objects.get(app_label=app_label, model=model)
+ location = ct.model_class()._default_manager.get(pk=pk)
+ except ObjectDoesNotExist:
+ raise Http404
+
+ events = self.get_event_queryset().filter(location_content_type=ct, location_pk=location.pk)
+
+ context = extra_context or {}
+ context.update({
+ 'location': location
+ })
+ return events, context
+
+ # Detail View.
+ def event_detail_view(self, request, year, month, day, slug, extra_context=None):
+ try:
+ event = Event.objects.select_related('parent_event').get(start_date__year=year, start_date__month=month, start_date__day=day, slug=slug)
+ except Event.DoesNotExist:
+ raise Http404
+
+ context = self.get_context()
+ context.update(extra_context or {})
+ context.update({
+ 'event': event
+ })
+ return self.event_detail_page.render_to_response(request, extra_context=context)
+
+ # Archive Views.
+ def tag_archive_view(self, request, extra_context=None):
+ tags = self.get_tag_queryset()
+ context = self.get_context()
+ context.update(extra_context or {})
+ context.update({
+ 'tags': tags
+ })
+ return self.tag_archive_page.render_to_response(request, extra_context=context)
+
+ def location_archive_view(self, request, extra_context=None):
+ # What datastructure should locations be?
+ locations = self.get_location_querysets()
+ context = self.get_context()
+ context.update(extra_context or {})
+ context.update({
+ 'locations': locations
+ })
+ return self.location_archive_page.render_to_response(request, extra_context=context)
+
+ def owner_archive_view(self, request, extra_context=None):
+ owners = self.get_owner_queryset()
+ context = self.get_context()
+ context.update(extra_context or {})
+ context.update({
+ 'owners': owners
+ })
+ return self.owner_archive_page.render_to_response(request, extra_context=context)
+
+ # Process page items
+ def process_page_items(self, request, items):
+ if self.events_per_page:
+ page_num = request.GET.get('page', 1)
+ paginator, paginated_page, items = paginate(items, self.events_per_page, page_num)
+ item_context = {
+ 'paginator': paginator,
+ 'paginated_page': paginated_page,
+ self.item_context_var: items
+ }
+ else:
+ item_context = {
+ self.item_context_var: items
+ }
+ return items, item_context
+
+ # Feed information hooks
+ def title(self, obj):
+ return obj.name
+
+ def link(self, obj):
+ # Link is ignored anyway...
+ return ""
+
+ def feed_guid(self, obj):
+ # Is this correct? Should I have a different id for different subfeeds?
+ return obj.uuid
+
+ def description(self, obj):
+ return obj.description
+
+ def feed_extra_kwargs(self, obj):
+ return {'filename': "%s.ics" % obj.slug}
+
+ def item_title(self, item):
+ return item.name
+
+ def item_description(self, item):
+ return item.description
+
+ def item_link(self, item):
+ return self.reverse(item)
+
+ def item_guid(self, item):
+ return item.uuid
+
+ def item_author_name(self, item):
+ if item.owner:
+ return item.owner.get_full_name()
+
+ def item_author_email(self, item):
+ return getattr(item.owner, 'email', None) or None
+
+ def item_pubdate(self, item):
+ return item.created
+
+ def item_categories(self, item):
+ return [tag.name for tag in item.tags.all()]
+
+ def item_extra_kwargs(self, item):
+ return {
+ 'start': item.get_start(),
+ 'end': item.get_end(),
+ 'last_modified': item.last_modified,
+ # Is forcing unicode enough, or should we look for a "custom method"?
+ 'location': force_unicode(item.location),
+ }
+
+ def __unicode__(self):
+ return u"%s for %s" % (self.__class__.__name__, self.calendar)
+
+field = CalendarView._meta.get_field('feed_type')
+field._choices += ((ICALENDAR, 'iCalendar'),)
+field.default = ICALENDAR
\ No newline at end of file