Anpassungen für das Hosting bei Djangoeurope und damit verbundenen Versionen Django 1.8 und Python 2.7
This commit is contained in:
committed by
Christian Berg
parent
cb4b15b3c6
commit
37d3cb78c1
0
src/events/__init__.py
Normal file
0
src/events/__init__.py
Normal file
50
src/events/admin.py
Normal file
50
src/events/admin.py
Normal file
@@ -0,0 +1,50 @@
|
||||
"""
|
||||
Created on 19.09.2011
|
||||
|
||||
@author: christian
|
||||
"""
|
||||
# import stuff we need from django
|
||||
from django.contrib import admin
|
||||
from imagekit.admin import AdminThumbnail
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from events.models import Event, Photo, Location
|
||||
|
||||
|
||||
class EventInline(admin.TabularInline):
|
||||
model = Event
|
||||
fields = ('name', 'start', 'end')
|
||||
verbose_name_plural = _('Event Series')
|
||||
|
||||
|
||||
class EventAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'start', 'end', 'location',)
|
||||
list_editable = ('start', 'end', 'location',)
|
||||
readonly_fields = ('event_series',)
|
||||
date_hierarchy = 'start'
|
||||
search_fields = ('name', 'description')
|
||||
list_per_page = 50
|
||||
inlines = (EventInline,)
|
||||
|
||||
|
||||
class LocationAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'street_address', 'postal_code', 'locality')
|
||||
|
||||
|
||||
class PhotoAdmin(admin.ModelAdmin):
|
||||
admin_thumbnail = AdminThumbnail(image_field='thumbnail')
|
||||
fields = ('image', 'event', 'name', 'description',
|
||||
('anchor_horizontal', 'anchor_vertical'),
|
||||
('photographer', 'created_date'))
|
||||
list_filter = ('event', 'on_startpage',)
|
||||
list_display = ('admin_thumbnail', 'image', 'name', 'event',
|
||||
'photographer', 'on_startpage')
|
||||
list_display_links = ('image',)
|
||||
list_editable = ('on_startpage', 'name', 'event', 'photographer')
|
||||
|
||||
|
||||
# register with CMS
|
||||
|
||||
admin.site.register(Event, EventAdmin)
|
||||
admin.site.register(Photo, PhotoAdmin)
|
||||
admin.site.register(Location, LocationAdmin)
|
||||
15
src/events/context_processors.py
Normal file
15
src/events/context_processors.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# -*- encoding: UTF-8 -*-
|
||||
"""
|
||||
Created on 30.09.2011
|
||||
|
||||
@author: christian
|
||||
"""
|
||||
from . import models
|
||||
|
||||
|
||||
def upcoming_events(request):
|
||||
return {
|
||||
'current_event': models.Event.objects.current_event(),
|
||||
'next_event': models.Event.objects.next_event(),
|
||||
'upcoming_events': models.Event.objects.upcoming(),
|
||||
}
|
||||
60
src/events/forms.py
Normal file
60
src/events/forms.py
Normal file
@@ -0,0 +1,60 @@
|
||||
"""
|
||||
Created on 03.10.2011
|
||||
|
||||
@author: christian
|
||||
"""
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from . import models
|
||||
from utils.html5.widgets import DateTimeInput
|
||||
|
||||
|
||||
user_query = get_user_model().objects.all()
|
||||
|
||||
|
||||
class PhotoUploadForm(forms.Form):
|
||||
error_css_class = 'error'
|
||||
required_css_class = 'required'
|
||||
photographer = forms.ModelChoiceField(user_query, required=True, )
|
||||
event = forms.ModelChoiceField(models.Event.objects.all(), required=True, )
|
||||
upload = forms.FileField(
|
||||
label=_('Images'),
|
||||
required=True,
|
||||
widget=forms.widgets.ClearableFileInput(
|
||||
attrs={
|
||||
'multiple': 'multiple',
|
||||
'accept': "image/gif,image/png,image/jpeg"
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class EditPhotoForm(forms.ModelForm):
|
||||
error_css_class = 'error'
|
||||
required_css_class = 'required'
|
||||
|
||||
class Meta(object):
|
||||
model = models.Photo
|
||||
fields = ('event', 'name', 'description', 'photographer',
|
||||
'anchor_horizontal', 'anchor_vertical',
|
||||
'created_date', 'on_startpage')
|
||||
|
||||
|
||||
class EventForm(forms.ModelForm):
|
||||
error_css_class = 'error'
|
||||
required_css_class = 'required'
|
||||
|
||||
start = forms.DateTimeField(
|
||||
label=_('start'), required=True,
|
||||
widget=DateTimeInput() # widget=SplitDateTimeWidget()
|
||||
)
|
||||
end = forms.DateTimeField(
|
||||
label=_('end'), required=False,
|
||||
widget=DateTimeInput() # widget=SplitDateTimeWidget()
|
||||
)
|
||||
|
||||
class Meta(object):
|
||||
model = models.Event
|
||||
exclude = ('event_count', 'event_series', )
|
||||
BIN
src/events/locale/de/LC_MESSAGES/django.mo
Normal file
BIN
src/events/locale/de/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
302
src/events/locale/de/LC_MESSAGES/django.po
Normal file
302
src/events/locale/de/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,302 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: kasu.events\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-01-05 19:23+0100\n"
|
||||
"PO-Revision-Date: 2014-12-08 16:06+0100\n"
|
||||
"Last-Translator: Christian Berg <xeniac.at@gmail.com>\n"
|
||||
"Language-Team: Kasu <verein@kasu.at>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Translated-Using: django-rosetta 0.7.2\n"
|
||||
"X-Generator: Poedit 1.6.11\n"
|
||||
|
||||
#: admin.py:17 models.py:81
|
||||
msgid "Event Series"
|
||||
msgstr "Veranstaltungsreihen"
|
||||
|
||||
#: forms.py:23
|
||||
msgid "Images"
|
||||
msgstr "Bilder"
|
||||
|
||||
#: forms.py:50
|
||||
msgid "start"
|
||||
msgstr "Beginn"
|
||||
|
||||
#: forms.py:54
|
||||
msgid "end"
|
||||
msgstr "Ende"
|
||||
|
||||
#: models.py:67 models.py:155
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: models.py:68 models.py:156
|
||||
msgid "Description"
|
||||
msgstr "Beschreibung"
|
||||
|
||||
#: models.py:70 templates/events/event_archive.html:41
|
||||
#: templates/events/event_detail.html:31 templates/events/event_detail.html:77
|
||||
#: templates/events/event_list.html:15
|
||||
msgid "Start"
|
||||
msgstr "Beginn"
|
||||
|
||||
#: models.py:71 templates/events/event_detail.html:32
|
||||
#: templates/events/event_detail.html:78
|
||||
msgid "End"
|
||||
msgstr "Ende"
|
||||
|
||||
#: models.py:72 models.py:159 templates/events/event_detail.html:37
|
||||
#: templates/events/event_detail.html:73 templates/events/event_detail.html:79
|
||||
msgid "Homepage"
|
||||
msgstr "Homepage"
|
||||
|
||||
#: models.py:73 models.py:157
|
||||
msgid "Image"
|
||||
msgstr "Bild"
|
||||
|
||||
#: models.py:75
|
||||
msgid "Tournament"
|
||||
msgstr "Turnier"
|
||||
|
||||
#: models.py:76
|
||||
msgid ""
|
||||
"This event is a tournament, different rules apply for the kyu "
|
||||
"ranking."
|
||||
msgstr ""
|
||||
"Diese Veranstaltung ist ein Turnier, es gelten andere Regeln für das Kyu "
|
||||
"Ranking."
|
||||
|
||||
#: models.py:82
|
||||
msgid ""
|
||||
"Wenn dieser Event zu einer Veranstaltungsreihe gehört werden Ort, "
|
||||
"Beschreibung, Bild und Homepage von dem hier angegebenen Event "
|
||||
"übernommen."
|
||||
msgstr ""
|
||||
"Wenn dieser Termin zu einer Veranstaltungsreihe gehört werden Ort, "
|
||||
"Beschreibung, Bild und Homepage von dem hier angegebenen Event übernommen."
|
||||
|
||||
#: models.py:88
|
||||
msgid "Event"
|
||||
msgstr "Termin"
|
||||
|
||||
#: models.py:89
|
||||
msgid "Events"
|
||||
msgstr "Termine"
|
||||
|
||||
#: models.py:160
|
||||
msgid "Postal Code"
|
||||
msgstr "Postleitzahl"
|
||||
|
||||
#: models.py:161
|
||||
msgid "Street Address"
|
||||
msgstr "Straße"
|
||||
|
||||
#: models.py:162
|
||||
msgid "Locality"
|
||||
msgstr "Ort"
|
||||
|
||||
#: models.py:163
|
||||
msgid "Country"
|
||||
msgstr "Land"
|
||||
|
||||
#: models.py:166
|
||||
msgid "Venue"
|
||||
msgstr "Veranstaltungsort"
|
||||
|
||||
#: models.py:167
|
||||
msgid "Venues"
|
||||
msgstr "Veranstaltungsorte"
|
||||
|
||||
#: views.py:101 templates/events/event_detail.html:110
|
||||
#: templates/events/event_form.html:9
|
||||
msgid "Edit Event"
|
||||
msgstr "Termin bearbeiten"
|
||||
|
||||
#: views.py:103 templates/events/event_form.html:9
|
||||
#: templates/events/page.html:15
|
||||
msgid "Add Event"
|
||||
msgstr "Neuer Termin"
|
||||
|
||||
#: views.py:199
|
||||
msgid "Event does not exist"
|
||||
msgstr "Veranstaltung gibt es nicht"
|
||||
|
||||
#: templates/events/event_archive.html:5 templates/events/event_archive.html:9
|
||||
msgid "Event Archive"
|
||||
msgstr "Veranstaltungsarchiv"
|
||||
|
||||
#: templates/events/event_archive.html:36 templates/events/event_list.html:11
|
||||
msgid "Event Image"
|
||||
msgstr "Veranstaltungsbild"
|
||||
|
||||
#: templates/events/event_archive.html:44 templates/events/event_list.html:18
|
||||
msgid "from"
|
||||
msgstr "von"
|
||||
|
||||
#: templates/events/event_archive.html:44 templates/events/event_list.html:18
|
||||
msgid "to"
|
||||
msgstr "bis"
|
||||
|
||||
#: templates/events/event_archive.html:52
|
||||
#: templates/events/event_detail.html:35 templates/events/event_detail.html:65
|
||||
#: templates/events/event_list.html:26
|
||||
msgid "Location"
|
||||
msgstr "Ort"
|
||||
|
||||
#: templates/events/event_archive.html:56
|
||||
#: templates/events/event_archive.html:57 templates/events/event_list.html:30
|
||||
msgid "Comments"
|
||||
msgstr "Kommentare"
|
||||
|
||||
#: templates/events/event_archive.html:60
|
||||
#: templates/events/event_archive.html:61
|
||||
#: templates/events/event_detail.html:39 templates/events/event_detail.html:49
|
||||
msgid "Photos"
|
||||
msgstr "Fotos"
|
||||
|
||||
#: templates/events/event_archive.html:64
|
||||
#: templates/events/event_archive.html:65
|
||||
#: templates/events/event_archive.html:66
|
||||
#: templates/events/event_detail.html:38 templates/events/event_detail.html:48
|
||||
#: templates/events/event_detail.html:50
|
||||
msgid "Hanchans"
|
||||
msgstr "Hanchans"
|
||||
|
||||
#: templates/events/event_archive.html:70
|
||||
msgid " Edit"
|
||||
msgstr "Bearbeiten"
|
||||
|
||||
#: templates/events/event_detail.html:40
|
||||
msgid "tourney"
|
||||
msgstr "Turnier"
|
||||
|
||||
#: templates/events/event_detail.html:40
|
||||
msgid "other rules apply here"
|
||||
msgstr "hier gelten andere Regeln"
|
||||
|
||||
#: templates/events/event_detail.html:48
|
||||
msgid "Info"
|
||||
msgstr "Info"
|
||||
|
||||
#: templates/events/event_detail.html:51
|
||||
msgid "Mai-Star Games"
|
||||
msgstr "Mai-Star Spiele"
|
||||
|
||||
#: templates/events/event_detail.html:54
|
||||
msgid "Tournament Ranking"
|
||||
msgstr "Turnier Wertung"
|
||||
|
||||
#: templates/events/event_detail.html:75
|
||||
msgid "Date"
|
||||
msgstr "Datum"
|
||||
|
||||
#: templates/events/event_detail.html:91
|
||||
msgid "Share on Google+"
|
||||
msgstr "Auf Google+ teilen"
|
||||
|
||||
#: templates/events/event_detail.html:92
|
||||
msgid "Share on Twitter"
|
||||
msgstr "Auf Twitter teilen"
|
||||
|
||||
#: templates/events/event_detail.html:93
|
||||
msgid "Share on Facebook"
|
||||
msgstr "Auf Facebook teilen"
|
||||
|
||||
#: templates/events/event_detail.html:94
|
||||
msgid "Show on Google Maps"
|
||||
msgstr "Auf Google Maps zeigen"
|
||||
|
||||
#: templates/events/event_form.html:19
|
||||
msgid "reset"
|
||||
msgstr "Zurücksetzen"
|
||||
|
||||
#: templates/events/event_form.html:20
|
||||
msgid "save"
|
||||
msgstr "Speichern"
|
||||
|
||||
#: templates/events/event_list.html:4 templates/events/event_list.html.py:5
|
||||
msgid "Upcoming Events"
|
||||
msgstr "Bevorstehende Veranstaltungen"
|
||||
|
||||
#: templates/events/event_list.html:41
|
||||
msgid " Upload"
|
||||
msgstr "Hochladen"
|
||||
|
||||
#: templates/events/page.html:10
|
||||
msgid "Add to Google Calendar"
|
||||
msgstr "Zu Google Kalender hinzufügen"
|
||||
|
||||
#~ msgid "left"
|
||||
#~ msgstr "Links"
|
||||
|
||||
#~ msgid "center"
|
||||
#~ msgstr "Mitte"
|
||||
|
||||
#~ msgid "right"
|
||||
#~ msgstr "Rechts"
|
||||
|
||||
#~ msgid "top"
|
||||
#~ msgstr "Oben"
|
||||
|
||||
#~ msgid "middle"
|
||||
#~ msgstr "Mitte"
|
||||
|
||||
#~ msgid "bottom"
|
||||
#~ msgstr "Unten"
|
||||
|
||||
#~ msgid "horizontal Anchorpoint"
|
||||
#~ msgstr "horizontaler Anker"
|
||||
|
||||
#~ msgid "vertical Anchorpoint"
|
||||
#~ msgstr "vertikaler Anker"
|
||||
|
||||
#~ msgid "Startpage"
|
||||
#~ msgstr "Startseite"
|
||||
|
||||
#~ msgid "Display this Photo on the Startpage Teaser"
|
||||
#~ msgstr "Foto als Teaser auf der Startseite verwenden."
|
||||
|
||||
#~ msgid "Published on"
|
||||
#~ msgstr "Veröffentlicht am"
|
||||
|
||||
#~ msgid "Number of views"
|
||||
#~ msgstr "Wie oft gesehen"
|
||||
|
||||
#~ msgid "Event Images"
|
||||
#~ msgstr "Veranstaltungsbilder"
|
||||
|
||||
#~ msgid "Cancel"
|
||||
#~ msgstr "Abbrechen"
|
||||
|
||||
#~ msgid "Delete"
|
||||
#~ msgstr "Löschen"
|
||||
|
||||
#~ msgid "previous"
|
||||
#~ msgstr "Zurück"
|
||||
|
||||
#~ msgid "download"
|
||||
#~ msgstr "Herunterladen"
|
||||
|
||||
#~ msgid "Photographer"
|
||||
#~ msgstr "Fotograf"
|
||||
|
||||
#~ msgid "on"
|
||||
#~ msgstr "am"
|
||||
|
||||
#~ msgid "Upload"
|
||||
#~ msgstr "Hochladen"
|
||||
|
||||
#~ msgid "delete"
|
||||
#~ msgstr "Löschen"
|
||||
|
||||
#~ msgid "upload"
|
||||
#~ msgstr "hochladen"
|
||||
181
src/events/models.py
Normal file
181
src/events/models.py
Normal file
@@ -0,0 +1,181 @@
|
||||
# -'- Encoding: utf-8 -*-
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from utils import COUNTRIES, OverwriteStorage
|
||||
from gallery.models import Photo
|
||||
from kasu import image_models
|
||||
|
||||
|
||||
def get_upload_path(instance, filename):
|
||||
"""
|
||||
Generates the desired file path and filename for an uploaded Image.
|
||||
With this function Django can save the uploaded images to subfolders that
|
||||
also have a meaning for humans.
|
||||
|
||||
@param instance: an Django Object for which the Image has been uploaded.
|
||||
@type instance: a instace of an models.Model sub-class.
|
||||
@param filename: The filename of the uploaded image.
|
||||
@type filename: String
|
||||
"""
|
||||
extension = filename[filename.rfind('.') + 1:]
|
||||
if isinstance(instance, Event):
|
||||
if instance.id:
|
||||
return "events/%s.%s" % (instance.id, extension)
|
||||
else:
|
||||
return "events/%s.%s" % (slugify(instance.name), extension)
|
||||
elif isinstance(instance, Location):
|
||||
if instance.id:
|
||||
return "events/location/%s.%s" % (instance.id, extension)
|
||||
else:
|
||||
return "events/location/%s.%s" % (instance.id, extension)
|
||||
elif isinstance(instance, Photo):
|
||||
return "events/%s/%s" % (instance.event.id, filename)
|
||||
|
||||
|
||||
class EventManager(models.Manager):
|
||||
def current_event(self):
|
||||
try:
|
||||
current = self.filter(start__lte=now())
|
||||
current = current.filter(end__gte=now())
|
||||
return current.order_by('start', 'end')[0]
|
||||
except:
|
||||
return None
|
||||
|
||||
def next_event(self):
|
||||
try:
|
||||
return self.filter(start__gt=now()).order_by('start', 'end')[0]
|
||||
except:
|
||||
return None
|
||||
|
||||
def archive(self):
|
||||
return self.filter(start__lt=now())
|
||||
|
||||
def upcoming(self, limit=3):
|
||||
result = self.filter(start__gt=now()).order_by('start', 'end')
|
||||
if limit:
|
||||
return result[1:(limit + 1)]
|
||||
else:
|
||||
return result
|
||||
|
||||
|
||||
class Event(image_models.ImageModel):
|
||||
name = models.CharField(_('Name'), max_length=255)
|
||||
description = models.TextField(_("Description"), blank=True)
|
||||
location = models.ForeignKey('Location')
|
||||
start = models.DateTimeField(_('Start'))
|
||||
end = models.DateTimeField(_('End'), blank=True, null=True)
|
||||
url = models.URLField(_('Homepage'), blank=True)
|
||||
image = models.ImageField(_("Image"), upload_to=get_upload_path,
|
||||
storage=OverwriteStorage(), blank=True, null=True)
|
||||
is_tournament = models.BooleanField(_('Tournament'), default=False,
|
||||
help_text=_(u'This event is a tournament, different rules apply for \
|
||||
the kyu ranking.'))
|
||||
photo_count = models.PositiveIntegerField(default=0, editable=False)
|
||||
event_series = models.ForeignKey('Event', blank=True, null=True,
|
||||
on_delete=models.SET_NULL, editable=False,
|
||||
verbose_name=_('Event Series'),
|
||||
help_text=_(u'Wenn dieser Event zu einer Veranstaltungsreihe gehört \
|
||||
werden Ort, Beschreibung, Bild und Homepage von dem hier angegebenen \
|
||||
Event übernommen.'))
|
||||
objects = EventManager()
|
||||
|
||||
class Meta(object):
|
||||
verbose_name = _('Event')
|
||||
verbose_name_plural = _('Events')
|
||||
ordering = ('-start', '-end',)
|
||||
|
||||
def __unicode__(self):
|
||||
try:
|
||||
return "%(name)s (%(date)s)" % {'name': self.name,
|
||||
'date': self.start.date()}
|
||||
except:
|
||||
return "New Event Model"
|
||||
|
||||
def get_absolute_url(self):
|
||||
kwargs = {
|
||||
'pk': self.id,
|
||||
'year': self.start.strftime('%Y'),
|
||||
'month': self.start.strftime('%m')
|
||||
}
|
||||
return reverse('event-detail', kwargs=kwargs)
|
||||
|
||||
def get_edit_url(self):
|
||||
kwargs = {
|
||||
'pk': self.id,
|
||||
'year': self.start.strftime('%Y'),
|
||||
'month': self.start.strftime('%m')
|
||||
}
|
||||
return reverse('event-form', kwargs=kwargs)
|
||||
|
||||
def get_callout(self):
|
||||
if self.image:
|
||||
return self.callout
|
||||
elif self.photo_set.count():
|
||||
return self.photo_set.all().order_by('?')[0].callout
|
||||
elif self.location.image:
|
||||
return self.location.callout
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_thumbnail(self):
|
||||
if self.image:
|
||||
return self.thumbnail
|
||||
elif self.photo_set.count():
|
||||
return self.photo_set.all().order_by('?')[0].thumbnail
|
||||
elif self.location.image:
|
||||
return self.location.thumbnail
|
||||
else:
|
||||
return None
|
||||
|
||||
def save(self, **kwargs):
|
||||
if self.event_series:
|
||||
master_event = self.event_series
|
||||
self.description = master_event.description
|
||||
self.location = master_event.location
|
||||
self.url = master_event.url
|
||||
self.image = master_event.image
|
||||
self.photo_count = self.photo_set.count()
|
||||
super(Event, self).save(**kwargs)
|
||||
|
||||
# Update the rest of the event series:
|
||||
for sub_event in Event.objects.filter(event_series=self):
|
||||
sub_event.save()
|
||||
|
||||
# Update the Hanchans if necesery:
|
||||
for hanchan in self.hanchan_set.all():
|
||||
hanchan.save()
|
||||
|
||||
|
||||
class Location(image_models.ImageModel):
|
||||
name = models.CharField(_("Name"), max_length=200)
|
||||
description = models.TextField(_("Description"), blank=True)
|
||||
image = models.ImageField(_("Image"), upload_to=get_upload_path,
|
||||
storage=OverwriteStorage(), blank=True, null=True)
|
||||
url = models.URLField(_('Homepage'), blank=True)
|
||||
postal_code = models.CharField(_('Postal Code'), max_length=6)
|
||||
street_address = models.CharField(_('Street Address'), max_length=127)
|
||||
locality = models.CharField(_('Locality'), max_length=127)
|
||||
country = models.CharField(_('Country'), max_length=2, choices=COUNTRIES)
|
||||
|
||||
class Meta(object):
|
||||
verbose_name = _('Venue')
|
||||
verbose_name_plural = _('Venues')
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
address = (self.street_address, self.locality, self.country,)
|
||||
return ','.join(address)
|
||||
|
||||
|
||||
models.signals.post_save.connect(image_models.regenerate_image_cache,
|
||||
sender=Event)
|
||||
models.signals.post_save.connect(image_models.regenerate_image_cache,
|
||||
sender=Location)
|
||||
76
src/events/templates/events/event_archive.html
Normal file
76
src/events/templates/events/event_archive.html
Normal file
@@ -0,0 +1,76 @@
|
||||
{% extends "events/page.html" %}
|
||||
{% load i18n comments%}
|
||||
|
||||
{% block title %}
|
||||
{% trans 'Event Archive' %} {% if month %}{{ month|date:'F Y' }} {% else %}{% if year %}{{year}}{% endif %}{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block teaser %}
|
||||
<h2>{% trans 'Event Archive' %} {% if month %}{{ month|date:'F Y' }}{% elif year %}{{year|date:'Y'}}{% endif %}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block redbox %}
|
||||
<h2>Archive</h2>
|
||||
<ul>
|
||||
{% if year %}
|
||||
{% for date in date_list %}
|
||||
<li><a href="{% url 'event-archive' year|date:'Y' date|date:'m' %}">{{ date|date:'F' }}</a></li>
|
||||
{% endfor %}
|
||||
{% elif month %}
|
||||
<li><a href="{% url 'event-archive' month|date:'Y' %}">{{ month|date:'Y' }}</a></li>
|
||||
{% else %}
|
||||
{% for date in date_list %}
|
||||
<li><a href="{% url 'event-archive' date|date:'Y' %}">{{ date|date:'Y' }}</a></li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
{% regroup event_list by start|date:'F Y' as month_list %}
|
||||
{% for month in month_list %}
|
||||
<h3 class="grid_12">{{ month.grouper }}</h3>
|
||||
{% for event in month.list %}
|
||||
{% get_comment_count for event as comment_count %}
|
||||
<a href="{{ event.get_absolute_url }}" class="grid_2"><img src="{{ event.get_thumbnail.url }}"
|
||||
alt="{% trans 'Event Image' %}"
|
||||
class="thumbnail"/></a>
|
||||
<div class="grid_4">
|
||||
<h4><a href="{{ event.get_absolute_url }}">{{ event.name }}</a></h4>
|
||||
|
||||
<p><img src="{{ STATIC_URL }}/icons/date.png" alt="{% trans 'Start' %}:" title="{% trans 'Start' %}">
|
||||
{{ event.start|date }}
|
||||
{% if event.end %}
|
||||
{% trans "from" %} {{ event.start|time:'H:i' }} {% trans "to" %} {{ event.end|time:'H:i' }}
|
||||
{% else %}
|
||||
{{ event.start|time:'H:i' }}
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
<p>{{event.description|truncatewords_html:20}}</p>
|
||||
<ul class="info">
|
||||
<li><img src="{{ STATIC_URL }}/icons/map.png" alt="{% trans 'Location' %}" title="{% trans 'Location' %}">
|
||||
{{ event.location }}
|
||||
</li>
|
||||
<li><a href="{{event.get_absolute_url}}#comments"><img src="{{ STATIC_URL }}/icons/comments.png"
|
||||
alt="{% trans 'Comments' %}"
|
||||
title="{% trans 'Comments' %}"> {{ comment_count }}</a>
|
||||
</li>
|
||||
<li><a href="{% url 'event-photo-list' event.pk %}"><img src="{{ STATIC_URL }}/icons/camera.png"
|
||||
alt="{% trans 'Photos' %}"
|
||||
title="{% trans 'Photos' %}">
|
||||
{{ event.photo_count }}</a></li>
|
||||
<li><a href="{% url 'event-hanchan-list' event.pk %}"><img src="{{ STATIC_URL }}/icons/table.png"
|
||||
alt="{% trans 'Hanchans' %}"
|
||||
title="{% trans 'Hanchans' %}">
|
||||
{{ event.hanchan_set.count }} {% trans 'Hanchans' %}</a></li>
|
||||
</ul>
|
||||
{% if perms.events.change_event %}
|
||||
<p class="right"><a href="{{ event.get_edit_url }}" class="button"><img src="{{ STATIC_URL }}icons/page_edit.png"
|
||||
alt="{%trans " Edit" %}"></a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if forloop.counter|divisibleby:2 %}<br class="clear"/>{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
144
src/events/templates/events/event_detail.html
Normal file
144
src/events/templates/events/event_detail.html
Normal file
@@ -0,0 +1,144 @@
|
||||
{% extends "events/page.html" %}
|
||||
{% load i18n django_markdown comments %}
|
||||
|
||||
{% block title %}{{ event.name }}{% endblock %}
|
||||
|
||||
{% block opengraph %}
|
||||
<meta property="og:type" content="activity" />
|
||||
<meta property="og:title" content="{{event.name}}" />
|
||||
<meta property="og:url" content="http://www.kasu.at{{event.get_absolute_url}}" />
|
||||
<meta property="og:image" content="http://www.kasu.at{{ event.get_thumbnail.url }}" />
|
||||
{% if event.description %}<meta property="og:description" content="{{event.description}}" />{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=false"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block jumbotron_background %} {{ event.get_callout.url }} {% endblock %}
|
||||
|
||||
{% block teaser %}
|
||||
<h1>{{event.name}}</h1>
|
||||
{% if event.description %}
|
||||
<div id="teaser_text">{{event.description|markdown|truncatewords_html:75}}</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block redbox %}
|
||||
<h2>Info</h2>
|
||||
<p> </p>
|
||||
<ul>
|
||||
<li class="date"><strong>{% trans "Start" %}:</strong> {{ event.start }}</li>
|
||||
{% if event.end %}<li class="date"><strong>{% trans "End" %}:</strong> {{ event.end }}</li>{% endif %}
|
||||
<li class="location">
|
||||
{% if event.location.url %}<a href="{{ event.location.url }}">{% else %}<a href="http://maps.google.com/maps?q={{event.location.address|urlencode}}&z=16">{% endif %}
|
||||
<strong>{% trans "Location" %}:</strong> {{event.location.name}}</a>
|
||||
</li>
|
||||
{% if event.url %}<li><a href="{{ event.url }}"><strong>{% trans "Homepage" %}:</strong> {{ event.url }}</a></li>{% endif %}
|
||||
<li class="hanchan"><a href="{% url 'event-hanchan-list' event.pk %}" ><strong>{% trans "Hanchans" %}:</strong> {{ event.hanchan_set.count }}</a></li>
|
||||
<li class="photo"><a href="{% url 'event-photo-list' event.pk %}"><strong>{% trans 'Photos' %}:</strong> {{ event.photo_count }}</a></li>
|
||||
{% if event.is_tournament %}<li class="season"><a href="{% url 'event-ranking' event.pk %}"><strong>{% trans "tourney" %}:</strong> {% trans "other rules apply here" %}</a></li>{% endif%}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block navigation %}
|
||||
<code>{{ event. }}</code>
|
||||
<ul id="navigation">
|
||||
<li><a href="{{ event.get_absolute_url }}"><img src="{{ STATIC_URL }}icons/information.png" alt="{% trans 'Hanchans' %}" /> {% trans 'Info' %}</a></li>
|
||||
<li><a href="{% url 'event-photo-list' event.pk %}"><img src="{{ STATIC_URL }}icons/camera.png" alt="{% trans 'Photos' %}" /> {{ event.photo_count }} {% trans 'Photos' %}</a></li>
|
||||
<li><a href="{% url 'event-hanchan-list' event.pk %}" ><img src="{{ STATIC_URL }}icons/table.png" alt="{% trans 'Hanchans' %}" /> {{ event.hanchan_set.count }} {% trans "Hanchans" %}</a></li>
|
||||
<li><a href="{% url 'maistar-game-list' event.pk %}" ><img src="{{ STATIC_URL }}icons/drink.png" alt="{% trans 'Mai-Star Games' %}" /> {{ event.maistargame_set.count }} {% trans "Mai-Star Games" %}</a></li>
|
||||
|
||||
{% if event.is_tournament %}
|
||||
<li><a href="{% url 'event-ranking' event.id %}"><img src="{{ STATIC_URL }}icons/medal_gold_1.png" alt="{% trans "Tournament Ranking" %}" /> {% trans "Tournament Ranking" %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
<div class="grid_6" id="google_maps">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="grid_6">
|
||||
<h3>{% trans 'Location' %}</h3>
|
||||
<strong>{{ event.location.name }}</strong>
|
||||
<address>
|
||||
{{event.location.street_address}}<br />
|
||||
{{event.location.postal_code}} {{event.location.locality}} <br />
|
||||
{{event.location.get_country_display}}
|
||||
</address>
|
||||
{% if event.location.url %}
|
||||
<p><strong>{% trans "Homepage" %}:</strong> <a href="{{ event.location.url }}">{{ event.location.url }}</a></p>
|
||||
{% endif %}
|
||||
<h3>{% trans "Date" %}</h3>
|
||||
<ul>
|
||||
<li><strong>{% trans "Start" %}:</strong> {{ event.start }}</li>
|
||||
{% if event.end %}<li><strong>{% trans "End" %}:</strong> {{ event.end }}</li>{% endif %}
|
||||
{% if event.url %}<li><strong>{% trans "Homepage" %}:</strong> <a href="{{ event.url }}">{{ event.url }}</a></li>{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="grid_12">
|
||||
{% if event.description %}
|
||||
{{event.description|markdown}}
|
||||
{% else %}
|
||||
{{event.location.description|markdown}}
|
||||
{% endif %}
|
||||
<p class="more_link">
|
||||
<a href="https://plus.google.com/share?url=http%3A%2F%2Fwww.kasu.at{{event.get_absolute_url|urlencode}}" onclick="javascript:window.open(this.href,
|
||||
'', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=600,width=600');return false;"><img src="{{STATIC_URL}}img/google_plus.png" alt="Google+" title="{% trans 'Share on Google+'%}" width="39" height="39"/></a>
|
||||
<a href="https://twitter.com/share?url=http%3A%2F%2Fwww.kasu.at{{event.get_absolute_url|urlencode}}" target='_blank'><img src="{{STATIC_URL}}img/twitter.png" alt="Twitter" title=" {% trans 'Share on Twitter' %}" width="39" height="39"/></a>
|
||||
<a href="http://facebook.com/sharer.php?u=http%3A%2F%2Fwww.kasu.at{{event.get_absolute_url|urlencode}}" target="_blank"><img src="{{STATIC_URL}}img/facebook.png" alt="Facebook" title="{% trans 'Share on Facebook'%}" width="39" height="39"/></a>
|
||||
<a href="http://maps.google.com/maps?q={{event.location.address|urlencode}}&z=16" target="gmaps"><img src="{{ STATIC_URL }}img/google_maps.png" alt="Google Maps" title="{% trans 'Show on Google Maps' %}" width="39" height="39"/></a>
|
||||
</p>
|
||||
</div>
|
||||
<br class="clear" />
|
||||
{% block event_content %} {% endblock %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block comments %}
|
||||
{% render_comment_list for event %}
|
||||
{% render_comment_form for event %}
|
||||
{% endblock %}
|
||||
|
||||
{% block buttonbar %}
|
||||
{% if perms.events.change_event %}
|
||||
<a class="button" href="{{ event.get_edit_url }}"><img src="{{ STATIC_URL }}icons/page_edit.png" alt="" /> {% trans "Edit Event" %}</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
var geocoder;
|
||||
var map;
|
||||
function codeAddress() {
|
||||
var address = "{{ event.location.address }}";
|
||||
geocoder.geocode( { 'address': address}, function(results, status) {
|
||||
if (status == google.maps.GeocoderStatus.OK) {
|
||||
map.setCenter(results[0].geometry.location);
|
||||
var marker = new google.maps.Marker({
|
||||
map: map,
|
||||
position: results[0].geometry.location
|
||||
});
|
||||
} else {
|
||||
alert("Geocode was not successful for the following reason: " + status);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
geocoder = new google.maps.Geocoder();
|
||||
var latlng = new google.maps.LatLng(-34.397, 150.644);
|
||||
var mapOptions = {
|
||||
zoom: 16,
|
||||
center: latlng,
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||
}
|
||||
map = new google.maps.Map(document.getElementById("google_maps"), mapOptions);
|
||||
codeAddress();
|
||||
}
|
||||
initialize();
|
||||
{% endblock %}
|
||||
28
src/events/templates/events/event_form.html
Normal file
28
src/events/templates/events/event_form.html
Normal file
@@ -0,0 +1,28 @@
|
||||
{% extends "events/page.html" %}
|
||||
{% load i18n %}
|
||||
{% block title %}{{ title }}{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
<form method="post" enctype="multipart/form-data" class="grid_12">
|
||||
{% csrf_token %}
|
||||
<fieldset>
|
||||
<legend>{% if event.pk %}{% trans "Edit Event"%}{% else %}{% trans "Add Event"%}{% endif %}</legend>
|
||||
{% include "form.html" %}
|
||||
{% if event.id and event.event_set.count %}
|
||||
<p class="warning">
|
||||
<strong>Achtung! Das ist eine Veranstaltungsreihe!</strong> Diese kann man im Moment nur im Admin-Interface vernünfig bearbeiten.<br />
|
||||
Du bearbeitest hier den "Hauptevent" der Reihe ({{event.event_set.count}}). Alle Änderungen (abgesehen von Name, Start und Ende) werden von den darauf folgendem Veranstaltungen übernommen.
|
||||
</strong>
|
||||
</p>
|
||||
{% endif %}
|
||||
<p class="buttonbar">
|
||||
<button type="reset"><img src="{{STATIC_URL}}icons/arrow_undo.png" alt="{% trans 'reset' %}" /> {% trans 'reset' %}</button>
|
||||
<button type="submit"><img src="{{STATIC_URL}}icons/disk.png" alt="{% trans 'save' %}" /> {% trans 'save' %}</button>
|
||||
</p>
|
||||
</fieldset>
|
||||
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block buttonbar %}{% endblock %}
|
||||
49
src/events/templates/events/event_list.html
Normal file
49
src/events/templates/events/event_list.html
Normal file
@@ -0,0 +1,49 @@
|
||||
{% extends "events/page.html" %}
|
||||
{% load i18n comments%}
|
||||
|
||||
{% block title %}{% trans "Upcoming Events" %}{% endblock %}
|
||||
{% block teaser%}<h2>{% trans "Upcoming Events" %}</h2>{% endblock %}
|
||||
{% block maincontent %}
|
||||
|
||||
{% for event in event_list %}
|
||||
{% ifchanged %}<h3 class="grid_12">{{ event.start|date:'F Y' }}</h3>{% endifchanged %}
|
||||
{% get_comment_count for event as comment_count %}
|
||||
<a href="{{ event.get_absolute_url }}" class="grid_2"><img src="{{ event.get_thumbnail.url }}" alt=" {% trans 'Event Image' %}"
|
||||
class="thumbnail"/></a>
|
||||
<div class="grid_4">
|
||||
<h4><a href="{{ event.get_absolute_url }}">{{ event.name }}</a></h4>
|
||||
<p class="strong"><img src="{{ STATIC_URL }}/icons/date.png" alt="{% trans 'Start' %}:" title="{% trans 'Start' %}">
|
||||
{{ event.start|date:'SHORT_DATE_FORMAT' }}
|
||||
{% if event.end %}
|
||||
{% trans "from" %} {{ event.start|time:'H:i' }} {% trans "to" %} {{ event.end|time:'H:i' }}
|
||||
{% else %}
|
||||
{{ event.start|time:'H:i' }}
|
||||
{% endif %}
|
||||
</p>
|
||||
<p>{{event.description|truncatewords_html:20}}</p>
|
||||
<ul class="info">
|
||||
<li>
|
||||
<img src="{{ STATIC_URL }}/icons/map.png" alt="{% trans 'Location' %}" title="{% trans 'Location' %}">
|
||||
{{ event.location }}
|
||||
</li>
|
||||
<li>
|
||||
<img src="{{ STATIC_URL }}/icons/comments.png" alt="{% trans 'Comments' %}" title="{% trans 'Comments' %}">
|
||||
<a href="{{event.get_absolute_url}}#comments">{{ comment_count }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="right">
|
||||
{% if perms.events.change_event %}
|
||||
<a href="{{ event.get_edit_url }}" class="button"><img src="{{ STATIC_URL }}icons/page_edit.png" alt="{%trans "
|
||||
Edit" %}"></a>
|
||||
{% endif %}
|
||||
{% if perms.events.add_photo %}
|
||||
<a href="{% url 'event-photo-list' event.pk %}" class="button"><img src="{{ STATIC_URL }}icons/image_add.png"
|
||||
alt="{%trans " Upload" %}"></a>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if page_obj.has_other_pages %}{% include 'paginator.html' %}{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
23
src/events/templates/events/event_site.html
Normal file
23
src/events/templates/events/event_site.html
Normal file
@@ -0,0 +1,23 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n django_markdown%}
|
||||
|
||||
{% block title %}{{ event.name }}{% endblock %}
|
||||
|
||||
{% block opengraph %}
|
||||
<meta property="og:type" content="activity" />
|
||||
<meta property="og:title" content="{{event.name}}" />
|
||||
<meta property="og:url" content="http://www.kasu.at{{event.get_absolute_url}}" />
|
||||
<meta property="og:image" content="http://www.kasu.at{{ event.get_thumbnail.url }}" />
|
||||
{% if event.description %}<meta property="og:description" content="{{event.description}}" />{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block jumbotron_background %}{{ event.get_callout.url }}')}{% endblock %}
|
||||
|
||||
{% block teaser %}
|
||||
<h2>{{event.name}}</h2>
|
||||
<div id="teaser_text">
|
||||
{% if event.description %}{{event.description|markdown}}{% else %}{{event.location.description|markdown}}{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
24
src/events/templates/events/page.html
Normal file
24
src/events/templates/events/page.html
Normal file
@@ -0,0 +1,24 @@
|
||||
{% extends "base.html" %}
|
||||
{% load comments i18n %}
|
||||
|
||||
{% block title %}{{page.title}}{% endblock %}
|
||||
|
||||
|
||||
{% block sidebar %}
|
||||
<a href="http://www.google.com/calendar/render?cid=http%3A%2F%2Fwww.kasu.at%2Fevents.ics"
|
||||
target="_blank"><img src="http://www.google.com/calendar/images/ext/gc_button6.gif"
|
||||
alt="{% trans 'Add to Google Calendar' %}"></a>
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_buttonbar %}
|
||||
{% if perms.events.add_event %}
|
||||
<a href="{% url 'event-form' %}" class="button"><img src="{{ STATIC_URL }}icons/calendar_add.png" alt=""/> {% trans 'Add Event' %}</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}{{ page.content }}{% endblock %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
16
src/events/tests.py
Normal file
16
src/events/tests.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
This file demonstrates writing tests using the unittest module. These will pass
|
||||
when you run "manage.py test".
|
||||
|
||||
Replace this with more appropriate tests for your application.
|
||||
"""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
"""
|
||||
self.assertEqual(1 + 1, 2)
|
||||
19
src/events/urls.py
Normal file
19
src/events/urls.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from .views import *
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^$', UpcomingEvents.as_view(), name='upcoming-events'),
|
||||
url(r'^(?P<year>[\d]{4})/$', EventArchiveYear.as_view(),
|
||||
name='event-archive'),
|
||||
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/$', EventArchiveMonth.as_view(),
|
||||
name='event-archive'),
|
||||
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/(?P<pk>[\d]+)/$',
|
||||
EventDetail.as_view(), name='event-detail'),
|
||||
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/(?P<pk>[\d]+)/edit/$',
|
||||
EventForm.as_view(), name='event-form'),
|
||||
url(r'^add/$', EventForm.as_view(), name='event-form'),
|
||||
url(r'^archive/$', EventArchiveIndex.as_view(), name='event-archive'),
|
||||
)
|
||||
265
src/events/views.py
Normal file
265
src/events/views.py
Normal file
@@ -0,0 +1,265 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Create your views here.
|
||||
from datetime import timedelta
|
||||
|
||||
from django.contrib.auth.decorators import permission_required
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponse, Http404
|
||||
from django.shortcuts import redirect
|
||||
from django.utils import timezone
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views import generic
|
||||
from icalendar import Calendar, Event
|
||||
import pyexiv2
|
||||
|
||||
from utils.mixins import PermissionRequiredMixin
|
||||
from . import models, forms
|
||||
|
||||
|
||||
class DeleteEventPhoto(generic.DeleteView):
|
||||
model = models.Photo
|
||||
"""
|
||||
def get_object(self, queryset=None):
|
||||
return models.Photo.objects.get(pk=self.kwargs['pk'])
|
||||
"""
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('event-photo-list', args=[self.object.event.id])
|
||||
|
||||
@method_decorator(permission_required('events.delete_photo'))
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(DeleteEventPhoto, self).dispatch(*args, **kwargs)
|
||||
|
||||
|
||||
class EventArchiveIndex(generic.ArchiveIndexView):
|
||||
allow_empty = True
|
||||
context_object_name = 'event_list'
|
||||
date_field = 'start'
|
||||
model = models.Event
|
||||
queryset = model.objects.all()
|
||||
paginate_by = 15
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = generic.ArchiveIndexView.get_context_data(self, **kwargs)
|
||||
context['is_archive'] = True
|
||||
return context
|
||||
|
||||
|
||||
class EventArchiveMonth(generic.MonthArchiveView):
|
||||
date_field = 'start'
|
||||
make_object_list = True
|
||||
model = models.Event
|
||||
month_format = '%m'
|
||||
paginate_by = 15
|
||||
template_name = 'events/event_archive.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = generic.MonthArchiveView.get_context_data(self, **kwargs)
|
||||
context['is_archive'] = True
|
||||
return context
|
||||
|
||||
|
||||
class EventArchiveYear(generic.YearArchiveView):
|
||||
date_field = 'start'
|
||||
make_object_list = True
|
||||
model = models.Event
|
||||
paginate_by = 15
|
||||
template_name = 'events/event_archive.html'
|
||||
year_format = '%Y'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = generic.YearArchiveView.get_context_data(self, **kwargs)
|
||||
context['is_archive'] = True
|
||||
return context
|
||||
|
||||
|
||||
class EventDetail(generic.DetailView):
|
||||
model = models.Event
|
||||
|
||||
|
||||
class EventDetailMixin(object):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(EventDetailMixin, self).get_context_data(**kwargs)
|
||||
if hasattr(self, 'event'):
|
||||
context['event'] = self.event
|
||||
else:
|
||||
context['event'] = self.object.event
|
||||
return context
|
||||
|
||||
|
||||
class EventForm(PermissionRequiredMixin, generic.UpdateView):
|
||||
form_class = forms.EventForm
|
||||
permission_required = 'events.add_event'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(EventForm, self).get_context_data(**kwargs)
|
||||
if self.kwargs.get('pk'):
|
||||
context['title'] = _("Edit Event")
|
||||
else:
|
||||
context['title'] = _("Add Event")
|
||||
return context
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
"""
|
||||
If an id has been submitted, try return the existing Event for an update,
|
||||
else creates a new one.
|
||||
@param queryset:
|
||||
"""
|
||||
if self.kwargs.get('pk'):
|
||||
event = models.Event.objects.get(pk=self.kwargs['pk'])
|
||||
if event.event_series:
|
||||
return event.event_series
|
||||
else:
|
||||
return event
|
||||
else:
|
||||
return models.Event()
|
||||
|
||||
|
||||
class EventGallery(generic.ListView):
|
||||
template_name = 'events/photo_gallery.html'
|
||||
queryset = models.Event.objects.filter(start__lt=timezone.now(),
|
||||
photo_count__gt=0)
|
||||
paginate_by = 12
|
||||
|
||||
|
||||
class EventListIcal(generic.View):
|
||||
"""
|
||||
Generates an returns an iCal File with all upcoming events.
|
||||
"""
|
||||
|
||||
def add_event(self, event):
|
||||
ics_event = Event()
|
||||
dtstart = timezone.localtime(event.start)
|
||||
dtend = timezone.localtime(event.end)
|
||||
|
||||
ics_event.add('DTSTART', dtstart)
|
||||
ics_event.add('SUMMARY', event.name)
|
||||
ics_event.add('DESCRIPTION', event.description)
|
||||
ics_event.add('LOCATION', event.location.address)
|
||||
ics_event.add('URL', 'http://www.kasu.at' + event.get_absolute_url())
|
||||
ics_event['UID'] = 'event-%d@www.kasu.at' % event.pk
|
||||
ics_event.add('PRIORITY', 5)
|
||||
if event.end:
|
||||
ics_event.add('DTEND', dtend)
|
||||
self.calendar.add_component(ics_event)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
response = HttpResponse(mimetype="text/calendar; charset=UTF-8")
|
||||
self.calendar = Calendar()
|
||||
self.calendar.add('prodid', 'http://www.kasu.at/')
|
||||
self.calendar.add('version', '2.0')
|
||||
for event in models.Event.objects.upcoming(limit=None):
|
||||
self.add_event(event)
|
||||
response.write(self.calendar.to_ical())
|
||||
return response
|
||||
|
||||
|
||||
class EventPhoto(generic.UpdateView):
|
||||
form_class = forms.EditPhotoForm
|
||||
model = models.Photo
|
||||
template_name = 'events/photo_detail.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(EventPhoto, self).get_context_data()
|
||||
event = models.Event.objects.get(id=self.kwargs['event'])
|
||||
context['event'] = event
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if request.POST.get('rotate') and request.user.has_perm(
|
||||
'events.change_photo'):
|
||||
photo = models.Photo.objects.get(pk=kwargs['pk'])
|
||||
photo.rotate(request.POST['rotate'])
|
||||
# return redirect(photo.get_absolute_url())
|
||||
return self.get(request)
|
||||
else:
|
||||
return generic.UpdateView.post(self, request, *args, **kwargs)
|
||||
|
||||
|
||||
class EventPhotoList(generic.ListView):
|
||||
context_object_name = 'photo_list'
|
||||
paginate_by = 36
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = generic.ListView.get_context_data(self, **kwargs)
|
||||
context['event'] = self.event
|
||||
context['form'] = forms.PhotoUploadForm(
|
||||
initial={'event': self.event, 'photographer': self.request.user})
|
||||
return context
|
||||
|
||||
def get_queryset(self):
|
||||
try:
|
||||
self.event = models.Event.objects.get(id=self.kwargs['event'])
|
||||
return models.Photo.objects.filter(event=self.event)
|
||||
except models.Event.DoesNotExist:
|
||||
raise Http404(_('Event does not exist'))
|
||||
|
||||
|
||||
class EventPhotoUpload(generic.FormView):
|
||||
form_class = forms.PhotoUploadForm
|
||||
template_name = 'events/photo_upload.html'
|
||||
|
||||
@method_decorator(permission_required('events.add_photo'))
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(EventPhotoUpload, self).dispatch(*args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = generic.FormView.get_context_data(self, **kwargs)
|
||||
context['event_list'] = models.Event.objects.archive()[:12]
|
||||
return context
|
||||
|
||||
def get_initial(self):
|
||||
"""
|
||||
Set the current logged in user a default value for the photographer.
|
||||
"""
|
||||
return {
|
||||
'photographer': self.request.user,
|
||||
}
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
"""
|
||||
|
||||
"""
|
||||
self.event = models.Event.objects.get(
|
||||
id=self.request.REQUEST.get('event'))
|
||||
photographer = self.request.POST.get('photographer',
|
||||
self.request.user.id)
|
||||
photographer = get_user_model().objects.get(id=photographer)
|
||||
self.counter = 1
|
||||
for upload in self.request.FILES.getlist('upload'):
|
||||
name = upload.name
|
||||
created_date, description = self.read_exif(upload)
|
||||
photo = models.Photo(
|
||||
event=self.event,
|
||||
photographer=photographer,
|
||||
image=upload,
|
||||
name=name,
|
||||
created_date=created_date,
|
||||
description=description
|
||||
)
|
||||
photo.save()
|
||||
self.counter += 1
|
||||
return redirect('event-photo-list', event=self.event.id)
|
||||
|
||||
def read_exif(self, photo):
|
||||
exif_data = pyexiv2.ImageMetadata.from_buffer(photo.read())
|
||||
exif_data.read()
|
||||
|
||||
try:
|
||||
created_date = exif_data['Exif.Image.DateTime'].value
|
||||
except:
|
||||
created_date = self.event.start + timedelta(minutes=self.counter)
|
||||
try:
|
||||
description = exif_data['Exif.Image.ImageDescription'].value
|
||||
except:
|
||||
description = ''
|
||||
return created_date, description
|
||||
|
||||
|
||||
class UpcomingEvents(generic.ListView):
|
||||
queryset = models.Event.objects.upcoming(limit=None)
|
||||
paginate_by = 16
|
||||
Reference in New Issue
Block a user