Another Step in the Quest to clean up the code base.

This commit is contained in:
2017-09-08 07:19:50 +02:00
parent ce218080b2
commit b3ab9798b5
229 changed files with 1915 additions and 15175 deletions

View File

@@ -1,9 +1,6 @@
"""
Created on 19.09.2011
"""Django admin interface for the event app.
@author: christian
"""
# import stuff we need from django
It's the best way to add eventseries, or edit/delete events."""
from django.contrib import admin
from django.utils.translation import gettext as _
@@ -11,12 +8,14 @@ from events.models import Event, Photo, Location
class EventInline(admin.TabularInline):
"""To list events of an eventseries below the 'master event'"""
model = Event
fields = ('name', 'start', 'end')
verbose_name_plural = _('Event Series')
class EventAdmin(admin.ModelAdmin):
"""Admin Interface to list and edit events."""
list_display = ('name', 'start', 'end', 'location',)
list_editable = ('start', 'end', 'location')
readonly_fields = ('event_series',)
@@ -27,11 +26,12 @@ class EventAdmin(admin.ModelAdmin):
class LocationAdmin(admin.ModelAdmin):
"""Admin Interace to list and edit event locations."""
list_display = ('name', 'street_address', 'postal_code', 'locality')
class PhotoAdmin(admin.ModelAdmin):
# admin_thumbnail = AdminThumbnail(image_field='thumbnail')
"""Admin Interface to list and edit photos of events."""
fields = ('image', 'event', 'name', 'description',
('photographer', 'created_date'))
list_filter = ('event', 'on_startpage',)
@@ -41,8 +41,6 @@ class PhotoAdmin(admin.ModelAdmin):
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)

View File

@@ -1,14 +1,22 @@
# -*- encoding: UTF-8 -*-
"""
Created on 30.09.2011
@author: christian
"""
""" Content processor to display upcoming events on every page you want. """
from django.core.cache import cache
from .models import Event
def upcoming_events(request):
def events_overview(request): # Ignore PyLintBear (W0613)
"""
Adds event information as variables to the template context on every page.
For speed reasons everything will be cached for an hour. the following
variables will be added to the template context:
* current_event: If an event is running at this moment, the correspondi
event object.
* next_event: the next event that is upcoming.
* upcoming_events: the next 3 events that are upcoming.
:param request: An Django HTTPRequest object
:return: dict() with the new context variables
"""
current_event = cache.get('current_event', False)
next_event = cache.get('next_event', False)
upcoming_events = cache.get('upcoming_events', False)

View File

@@ -1,22 +1,17 @@
"""
Created on 03.10.2011
@author: christian
"""
"""Django Forms to administrate the event content on the frontend."""
from django import forms
from django.utils.translation import ugettext as _
from django.contrib.auth import get_user_model
from django.utils.translation import ugettext as _
from . import models
user_query = get_user_model().objects.all()
class PhotoUploadForm(forms.Form):
"""Form to upload multiple photos to a single event."""
error_css_class = 'error'
required_css_class = 'required'
photographer = forms.ModelChoiceField(user_query, required=True, )
photographer = forms.ModelChoiceField(get_user_model().objects.all(),
required=True, )
event = forms.ModelChoiceField(models.Event.objects.all(), required=True, )
upload = forms.FileField(
label=_('Images'),
@@ -31,16 +26,19 @@ class PhotoUploadForm(forms.Form):
class EditPhotoForm(forms.ModelForm):
"""From to edit the metadata of a photo."""
error_css_class = 'error'
required_css_class = 'required'
class Meta(object):
"""Metadata to localize and customize the ModelForm."""
model = models.Photo
fields = ('event', 'name', 'description', 'photographer',
'created_date', 'on_startpage')
class EventForm(forms.ModelForm):
"""Form to add or edit an event."""
error_css_class = 'error'
required_css_class = 'required'
@@ -54,9 +52,13 @@ class EventForm(forms.ModelForm):
)
class Meta(object):
"""Metadata to localize and customize the ModelForm."""
model = models.Event
exclude = ('event_count', 'event_series', )
exclude = ('event_count', 'event_series',)
EventSeriesFormset = forms.inlineformset_factory(
models.Event, models.Event, fields=('start', 'end'), form=EventForm)
EventSeriesFormset = forms.inlineformset_factory( # Ignore PyLintBear (C0103)
models.Event,
models.Event,
fields=('start', 'end'),
form=EventForm)

View File

@@ -1,17 +1,18 @@
# -*- encoding: utf-8 -*-
""" urls for the event gallery part of the events app. """
from django.conf.urls import url
from .views import *
from . import views
urlpatterns = [
url(r'^$', EventGallery.as_view(), name='event-gallery'),
url(r'^(?P<event>[\d]+)/$', EventPhotoList.as_view(),
url(r'^$', views.EventGallery.as_view(), name='event-gallery'),
url(r'^(?P<event>[\d]+)/$', views.EventPhotoList.as_view(),
name='event-photo-list'),
url(r'^(?P<event>[\d]+)/upload/$', EventPhotoUpload.as_view(),
url(r'^(?P<event>[\d]+)/upload/$', views.EventPhotoUpload.as_view(),
name='event-photo-upload'),
url(r'^(?P<event>[\d]+)/(?P<pk>[\d]+)/$', EventPhoto.as_view(),
url(r'^(?P<event>[\d]+)/(?P<pk>[\d]+)/$', views.EventPhoto.as_view(),
name='event-photo'),
url(r'^delete/(?P<pk>[\d]+)/$', DeleteEventPhoto.as_view(),
url(r'^delete/(?P<pk>[\d]+)/$', views.DeleteEventPhoto.as_view(),
name='delete-event-photo'),
url(r'^upload/$', EventPhotoUpload.as_view(), name='event-photo-upload'),
url(r'^upload/$', views.EventPhotoUpload.as_view(),
name='event-photo-upload'),
]

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: kasu.events\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-10 23:16+0200\n"
"POT-Creation-Date: 2017-06-19 22:46+0200\n"
"PO-Revision-Date: 2016-09-28 00:24+0200\n"
"Last-Translator: Christian Berg <xeniac@posteo.at>\n"
"Language-Team: Kasu <verein@kasu.at>\n"
@@ -19,58 +19,58 @@ msgstr ""
"X-Generator: Poedit 1.8.9\n"
"X-Translated-Using: django-rosetta 0.7.6\n"
#: events/admin.py:16 events/models.py:114
#: events/admin.py:14 events/models.py:82
msgid "Event Series"
msgstr "Veranstaltungsreihen"
#: events/forms.py:23
#: events/forms.py:18
msgid "Images"
msgstr "Bilder"
#: events/forms.py:49
#: events/forms.py:46
msgid "start"
msgstr "Beginn"
#: events/forms.py:53
#: events/forms.py:50
msgid "end"
msgstr "Ende"
#: events/models.py:84 events/models.py:207 events/models.py:260
#: events/models.py:52 events/models.py:176 events/models.py:217
msgid "Name"
msgstr "Name"
#: events/models.py:85 events/models.py:208 events/models.py:268
#: events/models.py:53 events/models.py:177 events/models.py:225
msgid "Description"
msgstr "Beschreibung"
#: events/models.py:87 events/templates/events/event_detail.html:29
#: events/models.py:55 events/templates/events/event_detail.html:29
#: events/templates/events/event_detail.html:87
#: events/templates/events/event_list.html:28
#: events/templates/events/photo_upload.html:13
msgid "Start"
msgstr "Beginn"
#: events/models.py:88 events/templates/events/event_detail.html:30
#: events/models.py:56 events/templates/events/event_detail.html:30
#: events/templates/events/event_detail.html:89
msgid "End"
msgstr "Ende"
#: events/models.py:89 events/models.py:216
#: events/models.py:57 events/models.py:185
#: events/templates/events/event_detail.html:34
#: events/templates/events/event_detail.html:80
#: events/templates/events/event_detail.html:92
msgid "Homepage"
msgstr "Homepage"
#: events/models.py:91 events/models.py:210 events/models.py:262
#: events/models.py:59 events/models.py:179 events/models.py:219
msgid "Image"
msgstr "Bild"
#: events/models.py:98
#: events/models.py:66
msgid "Mahjong Tournament"
msgstr "Mahjong Turnier"
#: events/models.py:100
#: events/models.py:68
msgid ""
"This event is a tournament, different rules apply for the kyu "
"ranking."
@@ -78,11 +78,11 @@ msgstr ""
"Diese Veranstaltung ist ein Turnier, es gelten andere Regeln für das Kyu "
"Ranking."
#: events/models.py:104
#: events/models.py:72
msgid "Mahjong Season"
msgstr "Mahjong Saison"
#: events/models.py:115
#: events/models.py:83
msgid ""
"Wenn dieser Event zu einer Veranstaltungsreihe gehört werden Ort, "
"Beschreibung, Bild und Homepage von dem hier angegebenen Event "
@@ -91,72 +91,72 @@ msgstr ""
"Wenn dieser Termin zu einer Veranstaltungsreihe gehört werden Ort, "
"Beschreibung, Bild und Homepage von dem hier angegebenen Event übernommen."
#: events/models.py:124 events/models.py:226 events/models.py:290
#: events/models.py:92 events/models.py:195 events/models.py:247
msgid "first created at"
msgstr ""
#: events/models.py:129 events/models.py:231 events/models.py:295
#: events/models.py:97 events/models.py:200 events/models.py:252
msgid "latest updated at"
msgstr ""
#: events/models.py:134
#: events/models.py:103
msgid "Event"
msgstr "Termin"
#: events/models.py:135
#: events/models.py:104
msgid "Events"
msgstr "Termine"
#: events/models.py:148
#: events/models.py:117
msgid "A event can't end before it had started"
msgstr "Eine Veranstaltung kann nicht enden bevor sie begonnen hat"
#: events/models.py:217
#: events/models.py:186
msgid "Postal Code"
msgstr "Postleitzahl"
#: events/models.py:218
#: events/models.py:187
msgid "Street Address"
msgstr "Straße"
#: events/models.py:219
#: events/models.py:188
msgid "Locality"
msgstr "Ort"
#: events/models.py:220
#: events/models.py:189
msgid "Country"
msgstr "Land"
#: events/models.py:235
#: events/models.py:204
msgid "Venue"
msgstr "Veranstaltungsort"
#: events/models.py:236
#: events/models.py:205
msgid "Venues"
msgstr "Veranstaltungsorte"
#: events/models.py:274
#: events/models.py:231
msgid "Startpage"
msgstr "Startseite"
#: events/models.py:277
#: events/models.py:234
msgid "Display this Photo on the Startpage Teaser"
msgstr "Foto als Teaser auf der Startseite verwenden."
#: events/models.py:279
#: events/models.py:236
msgid "Published on"
msgstr "Veröffentlicht am"
#: events/models.py:281
#: events/models.py:238
msgid "Number of views"
msgstr "Wie oft gesehen"
#: events/models.py:306 events/templates/events/event_archive.html:38
#: events/models.py:262 events/templates/events/event_archive.html:38
#: events/templates/events/event_list.html:18
msgid "Event Image"
msgstr "Veranstaltungsbild"
#: events/models.py:307
#: events/models.py:263
msgid "Event Images"
msgstr "Veranstaltungsbilder"
@@ -253,7 +253,7 @@ msgid "Show on Google Maps"
msgstr "Auf Google Maps zeigen"
#: events/templates/events/event_detail.html:127
#: events/templates/events/event_form.html:9 events/views.py:106
#: events/templates/events/event_form.html:9 events/views.py:104
msgid "Edit Event"
msgstr "Termin bearbeiten"
@@ -262,16 +262,16 @@ msgid "Add Dates"
msgstr "Termine hinzufügen"
#: events/templates/events/event_form.html:9
#: events/templates/events/page.html:9 events/views.py:108
#: events/templates/events/page.html:9 events/views.py:106
msgid "Add Event"
msgstr "Neuer Termin"
#: events/templates/events/event_form.html:19
#: events/templates/events/event_form.html:18
#: events/templates/events/photo_list.html:35
msgid "reset"
msgstr "Zurücksetzen"
#: events/templates/events/event_form.html:20
#: events/templates/events/event_form.html:19
#: events/templates/events/eventseries_form.html:25
msgid "save"
msgstr "Speichern"
@@ -328,7 +328,7 @@ msgstr "Speichern"
msgid "Upload"
msgstr "Hochladen"
#: events/views.py:209
#: events/views.py:203
msgid "Event does not exist"
msgstr "Veranstaltung gibt es nicht"

40
src/events/managers.py Normal file
View File

@@ -0,0 +1,40 @@
"""Django ORM Managers for the event models."""
from django.db import models
from django.utils.timezone import now
class EventManager(models.Manager):
"""Django ORM Manager that adds some queryshortcuts to Event Models."""
def get_queryset(self):
"""Joins the location info to every event query."""
return super(EventManager, self).get_queryset().select_related(
'location')
def current_event(self):
"""Returns the event that is currently running."""
try:
current = self.filter(start__lte=now())
current = current.filter(end__gte=now())
return current.order_by('start', 'end')[0]
except IndexError:
return None
def next_event(self):
"""Returns the next upcoming event."""
try:
return self.filter(start__gt=now()).order_by('start', 'end')[0]
except IndexError:
return None
def archive(self):
"""Returns all past events."""
return self.filter(start__lt=now())
def upcoming(self, limit=None):
"""Returns the next 'limit' upcoming events.
:param limit: how many upcoming events should be returned?
"""
result = self.filter(start__gt=now()).order_by('start', 'end')
return result[0:limit] if limit else result

43
src/events/mixins.py Normal file
View File

@@ -0,0 +1,43 @@
"""Mixins for Events."""
from . import models
# Ignore PyLintBear (R0903)
class EventArchiveMixin(object):
"""Adds an is_archive = True variable to the template context."""
context_object_name = 'event_list'
date_field = 'start'
make_object_list = True
model = models.Event
ordering = ('start', 'end')
paginate_by = 15
template_name = 'events/event_archive.html'
def get_context_data(self, **kwargs):
"""Add is_archive to the context and set it to true.
:return: TemplateContext object"""
context = super(EventArchiveMixin, self).get_context_data(**kwargs)
context['is_archive'] = True
return context
# Ignore PyLintBear (R0903)
class EventDetailMixin(object):
"""A very simple Mixin to add the related event to the template context."""
event = None
def get_context_data(self, **kwargs):
"""Add self.event or the related event of self.object to the template
context.
:return: TemplateContext object"""
context = super(EventDetailMixin, self).get_context_data(**kwargs)
if hasattr(self, 'event') and self.event:
context['event'] = self.event
elif hasattr(self, 'object') and isinstance(self.object, models.Event):
context['event'] = self.object
elif hasattr(self, 'object') and hasattr(self.object, 'event'):
context['event'] = self.object.event
print(context)
return context

View File

@@ -1,5 +1,4 @@
# -'- Encoding: utf-8 -*-
"""Models to solitary events, events series with an location and photos."""
import os
from ckeditor.fields import RichTextField
@@ -14,6 +13,7 @@ from django.utils.translation import ugettext as _
from easy_thumbnails.fields import ThumbnailerImageField
from utils import COUNTRIES, OverwriteStorage
from .managers import EventManager
def get_upload_path(instance, filename):
@@ -47,40 +47,8 @@ def get_upload_path(instance, filename):
)
class EventManager(models.Manager):
def get_queryset(self):
return super(EventManager, self).get_queryset().select_related(
'location')
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 IndexError:
return None
def next_event(self):
try:
return self.filter(start__gt=now()).order_by('start', 'end')[0]
except IndexError:
return None
def archive(self):
return self.filter(start__lt=now())
def latest_events(self, num=3):
return self.filter(start__lt=now()).order_by('-start', '-end')[:num]
def upcoming(self, limit=None):
result = self.filter(start__gt=now()).order_by('start', 'end')
if limit:
return result[0:limit]
else:
return result
class Event(models.Model):
"""An Event that could be a tournament, a game session, or an convention."""
name = models.CharField(_('Name'), max_length=255)
description = RichTextField(_("Description"), blank=True)
location = models.ForeignKey('Location')
@@ -131,6 +99,7 @@ class Event(models.Model):
objects = EventManager()
class Meta(object):
"""order the events by start date."""
verbose_name = _('Event')
verbose_name_plural = _('Events')
ordering = ('start', 'end',)
@@ -244,18 +213,6 @@ class Location(models.Model):
return ','.join(address)
class PhotoManager(models.Manager):
def get_random(self, startpage=True):
if startpage:
queryset = self.filter(on_startpage=True)
else:
queryset = self.all().order_by('?')[0]
try:
return queryset.order_by('?')[0]
except IndexError:
return Photo()
class Photo(models.Model):
name = models.CharField(_("Name"), max_length=100, blank=True)
image = ThumbnailerImageField(
@@ -295,7 +252,6 @@ class Photo(models.Model):
verbose_name=_('latest updated at'),
)
objects = PhotoManager()
metadata = None
orientation = 1

View File

@@ -1,20 +1,23 @@
"""To geneate a Sitemap with all events."""
from django.contrib.sitemaps import Sitemap
from django.utils import timezone
from .models import Event
from .models import Photo
class EventSitemap(Sitemap):
"""To add an event to the global sitemap."""
changefreq = "never"
protocol = 'https'
def items(self):
"""add all events to the sitemap."""
return Event.objects.all()
def priority(self, event):
delta = timezone.now() - event.start
delta = abs(delta.days / 300.0)
"""give events closer to the present a higer priority for crawlers."""
delta = abs((timezone.now() - event.start) / 300.0)
return max(1 - delta, 0.1)
def lastmod(self, event):
"""return the last modification date."""
return event.date_modified

View File

@@ -25,7 +25,7 @@ if ($('a.next').attr('href')) {
{% block teaser %}
<h1 class="grid_12">{{event.name}} - {{ photo.name }}</h1>
{% if event.description %}
<div id="teaser_text">{{event.description|truncatewords_html:75}}</div>
<div id="teaser_text">{{event.description|truncatewords_html:75|safe}}</div>
{% endif %}
{% endblock %}

View File

@@ -1,17 +1,20 @@
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
This file should test the functionality of the events app using the unittest
module. These will pass when you run "manage.py test".
Replace this with more appropriate tests for your application.
Usefull tests have to been written yet. sorry!
"""
from django.test import TestCase
class SimpleTest(TestCase):
class EventTest(TestCase):
""" Here we should test the creation and modifiaction of Events. """
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.assertEqual(1 + 1, 2)
class LocationTest(TestCase):
""" Here we should test the creation and modifiaction of Locations. """
class PhotoTest(TestCase):
""" Here we should test the creation and modifiaction of Photos. """

View File

@@ -1,21 +1,22 @@
# -*- encoding: utf-8 -*-
"""URLS to access upcoming events and the event archive."""
from django.conf.urls import url
from django.views.generic import RedirectView
from .views import *
from . import views
urlpatterns = [
url(r'^$', RedirectView.as_view(url='/events/upcoming/', permanent=True)),
url(r'^(?P<year>[\d]{4})/$', EventArchiveYear.as_view(),
url(r'^(?P<year>[\d]{4})/$', views.EventArchiveYear.as_view(),
name='event-archive'),
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/$', EventArchiveMonth.as_view(),
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/$',
views.EventArchiveMonth.as_view(),
name='event-archive'),
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/(?P<pk>[\d]+)/$',
EventDetail.as_view(), name='event-detail'),
views.EventDetail.as_view(), name='event-detail'),
url(r'^(?P<year>[\d]{4})/(?P<month>[\d]+)/(?P<pk>[\d]+)/add_dates/$',
EventSeriesForm.as_view(), name='eventseries-form'),
views.EventSeriesForm.as_view(), name='eventseries-form'),
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'),
url(r'^upcoming/$', UpcomingEvents.as_view(), name='upcoming-events'),
views.EventForm.as_view(), name='event-form'),
url(r'^add/$', views.EventForm.as_view(), name='event-form'),
url(r'^archive/$', views.EventArchiveIndex.as_view(), name='event-archive'),
url(r'^upcoming/$', views.UpcomingEvents.as_view(), name='upcoming-events'),
]

View File

@@ -1,107 +1,63 @@
# -*- encoding: utf-8 -*-
# Create your views here.
""" All views to display or edit events and event-photos. """
from datetime import timedelta
from django.db.models import Q
from django.contrib.auth.decorators import permission_required
from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.urlresolvers import reverse
from extra_views import InlineFormSetView
from extra_views import ModelFormSetView
from django.db.models import Q
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 extra_views import InlineFormSetView
from icalendar import Calendar, Event
from utils.mixins import PermissionRequiredMixin
from . import models, forms
from . import forms, mixins, models
class DeleteEventPhoto(generic.DeleteView):
class DeleteEventPhoto(PermissionRequiredMixin, mixins.EventDetailMixin,
generic.DeleteView):
"""Delete a requested photo and redirect to the album view."""
model = models.Photo
permission_required = 'events.delete_photo'
def get_success_url(self):
return reverse('event-photo-list', args=[self.object.event.id])
def get_context_data(self, **kwargs):
context = super(DeleteEventPhoto, self).get_context_data()
context['event'] = self.object.event
return context
@method_decorator(permission_required('events.delete_photo'))
def dispatch(self, *args, **kwargs):
return super(DeleteEventPhoto, self).dispatch(*args, **kwargs)
"""Redirect to the album view of the event from the deleted image."""
return reverse('event-photo-list', args=[self.object.event_id])
class EventArchiveIndex(generic.ArchiveIndexView):
class EventArchiveIndex(mixins.EventArchiveMixin, generic.ArchiveIndexView):
"""Index of the event archive, displays the upcoming events first."""
allow_empty = True
context_object_name = 'event_list'
date_field = 'start'
model = models.Event
ordering = ('-start', '-end')
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
ordering = ('start', 'end')
class EventArchiveMonth(mixins.EventArchiveMixin, generic.MonthArchiveView):
"""List the events from the specific month of the given year."""
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):
model = models.Event
date_field = 'start'
make_object_list = True
ordering = ('start', 'end')
paginate_by = 15
template_name = 'events/event_archive.html'
class EventArchiveYear(mixins.EventArchiveMixin, generic.YearArchiveView):
"""List all events from the specified year."""
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):
class EventDetail(mixins.EventDetailMixin, generic.DetailView):
"""Detail View to see all details of an event."""
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):
class EventForm(PermissionRequiredMixin, mixins.EventDetailMixin,
generic.UpdateView):
"""Frontend formular to add or edit a Event."""
form_class = forms.EventForm
template_name = 'events/event_form.html'
permission_required = 'events.add_event'
def get_context_data(self, **kwargs):
"""Dynamicle set the title to Add or Edit Event, depanding if an
event ID was given, or not."""
context = super(EventForm, self).get_context_data(**kwargs)
if self.kwargs.get('pk'):
context['title'] = _("Edit Event")
@@ -110,18 +66,15 @@ class EventForm(PermissionRequiredMixin, generic.UpdateView):
return context
def get_object(self, queryset=None):
"""Try return the existing Event for an update if an id has been
submitted, else create a new one.
"""
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'):
return models.Event.objects.get(pk=self.kwargs['pk'])
else:
return models.Event()
return models.Event.objects.get(pk=self.kwargs['pk']) \
if self.kwargs.get('pk') else models.Event()
class EventGallery(generic.ListView):
class EventGallery(mixins.EventDetailMixin, generic.ListView):
"""Display a overview of all event photo albums."""
template_name = 'events/photo_gallery.html'
queryset = models.Event.objects.filter(
start__lt=timezone.now(),
@@ -132,69 +85,56 @@ class EventGallery(generic.ListView):
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)
"""Generates an returns an iCal File with all upcoming events."""
def get(self, request, *args, **kwargs):
"""Add all upcoming events to an .ics file and send it."""
response = HttpResponse(content_type="text/calendar; charset=UTF-8")
self.calendar = Calendar()
self.calendar.add('prodid', 'http://www.kasu.at/')
self.calendar.add('version', '2.0')
calendar = Calendar()
calendar.add('prodid', 'http://www.kasu.at/')
calendar.add('version', '2.0')
for event in models.Event.objects.upcoming(limit=None):
self.add_event(event)
response.write(self.calendar.to_ical())
ics_event = Event()
ics_event.add('DTSTART', timezone.localtime(event.start))
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', timezone.localtime(event.end))
calendar.add_component(ics_event)
response.write(calendar.to_ical())
return response
class EventPhoto(generic.UpdateView):
class EventPhoto(mixins.EventDetailMixin, generic.UpdateView):
"""Display the requested Photo and allows rotation if the user has change
permissions."""
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()
try:
event = models.Event.objects.get(id=self.kwargs['event'])
except models.Event.DoesNotExist:
event = self.object.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):
class EventPhotoList(mixins.EventDetailMixin, generic.ListView):
"""List all Photos of the event or event series in an album."""
context_object_name = 'photo_list'
event = None
paginate_by = 36
def get_context_data(self, **kwargs):
context = generic.ListView.get_context_data(self, **kwargs)
context['event'] = self.event
context = super(EventPhotoList, self).get_context_data(**kwargs)
context['form'] = forms.PhotoUploadForm(
initial={'event': self.event, 'photographer': self.request.user})
return context
@@ -210,13 +150,10 @@ class EventPhotoList(generic.ListView):
raise Http404(_('Event does not exist'))
class EventPhotoUpload(generic.FormView):
class EventPhotoUpload(mixins.EventDetailMixin, 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)
permission_required = 'events.add_photo'
def get_context_data(self, **kwargs):
context = generic.FormView.get_context_data(self, **kwargs)
@@ -224,45 +161,30 @@ class EventPhotoUpload(generic.FormView):
return context
def get_initial(self):
"""
Set the current logged in user a default value for the photographer.
"""
return {
'photographer': self.request.user,
}
""" Set the current user as 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)
event = models.Event.objects.get(id=self.request.POST.get('event'))
photographer = get_user_model().objects.get(
id=self.request.POST.get('photographer', self.request.user.id))
counter = 0
for image_file in self.request.FILES.getlist('upload'):
photo = models.Photo(
event=self.event,
event=event,
photographer=photographer,
image=upload,
name=name,
created_date=created_date,
description=description
image=image_file,
name=image_file.name,
created_date=event.start + timedelta(minutes=counter),
description=''
)
photo.save()
self.counter += 1
return redirect('event-photo-list', event=self.event.id)
def read_exif(self, photo):
created_date = self.event.start + timedelta(minutes=self.counter)
description = ''
return created_date, description
counter += 1
return redirect('event-photo-list', event=event.id)
class EventSeriesForm(EventDetailMixin, PermissionRequiredMixin, InlineFormSetView):
class EventSeriesForm(mixins.EventDetailMixin, PermissionRequiredMixin,
InlineFormSetView):
model = models.Event
inline_model = models.Event
fk_name = 'event_series'