UPD: added app to submit participant registrations.

This commit is contained in:
2019-02-08 16:44:53 +01:00
parent b3abadf2a8
commit f1a97c66a0
49 changed files with 1156 additions and 0 deletions

View File

@@ -0,0 +1 @@
default_app_config = 'dav_registration.apps.AppConfig'

View File

@@ -0,0 +1,8 @@
from django.contrib import admin
from .models import Registration
@admin.register(Registration)
class RegistrationAdmin(admin.ModelAdmin):
pass

17
dav_registration/apps.py Normal file
View File

@@ -0,0 +1,17 @@
from django.core.exceptions import ImproperlyConfigured
from dav_base.config.apps import AppConfig as _AppConfig, DefaultSetting
DEFAULT_SETTINGS = (
DefaultSetting('privacy_policy', ImproperlyConfigured),
)
class AppConfig(_AppConfig):
name = 'dav_registration'
verbose_name = u'DAV Kurs-Anmeldungen'
default_settings = DEFAULT_SETTINGS
def ready(self):
from . import signals
signals.registration_created.connect(signals.send_emails_on_registration)

View File

@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
PRIVACY_POLICY = u"""Im Rahmen deiner Anmeldung werden eine Reihe von Daten erhoben, verarbeitet und gespeichert.
Wofür werden diese Daten benötigt?
Zunächst muss die Tourenleitung entscheiden, ob du die erforderlichen Anforderungen zur Teilnahme an der jeweiligen\
Veranstaltung erfüllst. Dazu muss die Tourenleitung ein paar Informationen über dich haben und dich gegebenenfalls\
für Rückfragen kontaktieren können.
Wenn für die Veranstaltung ein Teilnehmerbeitrag erhoben wird, dann benötigt auch die Geschäftstelle der Sektion\
Karlsruhe eine Teilnehmerliste um die Zahlungseingänge zuordnen zu können.
Und für den unwahrscheinlichen Fall, dass bei der Veranstaltung etwas schief geht, kann eine Liste mit Teilnehmerdaten\
und deren Notfall-Kontakten natürlich notwendig werden.
Letzlich müssen wir als Veranstalter irgendwie wissen, wer mit uns unterwegs ist.
Wer verarbeitet die Daten?
Da die Anmeldedaten per E-Mail an die Tourenleitung übermittelt werden, sind in die Datenverarbeitung auch\
EDV-Systeme privater Internetdiensteanbierter involviert. Hierauf haben wir keinen Einfluss.
Ebenso werden die Anmeldedaten an die von dir angegebene E-Mail-Adresse gesendet. Auch hierbei sind eventuell\
Dritte beteiligt (z.B. dein E-Mail- oder Internetprovider).
Ansonsten erfolgt die Datenverarbeitung und Speicherung durch haupt- und ehrenamtliche Mitarbeiter der\
Sektion Karlsruhe des Deutschen Alpenvereins (DAV) e.V.
Was geschieht mit den Daten?
Die gespeicherten Daten werden ausschließlich zu Zwecken verwendet, die zur ordnungsgemäßen Durchführung der\
jeweiligen Veranstaltung notwendig sind.
Nach Beendigung der Veranstaltung, Erfüllung aller Pflichten und organisatorischem Abschluss der Veranstaltung\
werden die gespeicherten Daten gelöscht.
"""

View File

@@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
from dav_base.emails import AbstractMail
class AbstractRegistrationMail(AbstractMail):
def __init__(self, recipient, registration):
self._recipient = recipient
self._registration = registration
self._event = registration.event
def _get_subject(self, subject_fmt=None, **kwargs):
if subject_fmt is None:
subject_fmt = self._subject
if self._event.number:
subject_fmt = u'%s: %s' % (self._event.number, subject_fmt)
return super(AbstractRegistrationMail, self)._get_subject(subject_fmt=subject_fmt, **kwargs)
def _get_recipients(self):
if hasattr(self._recipient, 'get_full_name') and hasattr(self._recipient, 'email'):
r = u'"{fullname}" <{email}>'.format(fullname=self._recipient.get_full_name(),
email=self._recipient.email)
else:
r = self._recipient
return [r]
def _get_context_data(self, extra_context=None):
context = super(AbstractRegistrationMail, self)._get_context_data(extra_context=extra_context)
context['recipient'] = self._recipient
context['registration'] = self._registration
context['event'] = self._event
return context
class InformTrainerRegistrationMail(AbstractRegistrationMail):
_subject = u'Anmeldung'
_template_name = 'dav_registration/emails/inform_trainer.txt'
def _get_reply_to(self):
s = u'"{fullname}" <{email}>'.format(fullname=self._registration.get_full_name(),
email=self._registration.email_address)
return [s]
class InformSelfRegistrationMail(AbstractRegistrationMail):
_subject = u'Deine Anmeldung'
_template_name = 'dav_registration/emails/inform_self.txt'
def _get_reply_to(self):
s = u'"{fullname}" <{email}>'.format(fullname=self._event.owner.get_full_name(),
email=self._event.owner.email)
return [s]

43
dav_registration/forms.py Normal file
View File

@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
import logging
from django import forms
from django.utils.translation import ugettext, ugettext_lazy as _
from .models import Registration
logger = logging.getLogger(__name__)
class RegistrationForm(forms.ModelForm):
class Meta:
model = Registration
exclude = ['event', 'created_at', 'privacy_policy', 'purge_at']
widgets = {
'emergency_contact': forms.Textarea(attrs={'rows': 4}),
'experience': forms.Textarea(attrs={'rows': 5}),
'note': forms.Textarea(attrs={'rows': 5}),
}
def clean_experience(self):
val = self.cleaned_data.get('experience')
if val == '':
need_experience = True
if self.instance.event.sport == 'W':
need_experience = False
if need_experience:
raise forms.ValidationError(
ugettext(u'Die Tourenleiter*innen brauchen ein paar Angaben,'
u' was du bereits kannst oder wie fit du bist.'),
code='need_experience',
)
return val
def clean_privacy_policy_accepted(self):
val = self.cleaned_data.get('privacy_policy_accepted')
if not val and self.instance.privacy_policy:
raise forms.ValidationError(
ugettext(u'Wir müssen deine Daten leider speichern können,'
u' damit wir wissen, dass du dich angemeldet hast.'),
code='privacy_policy_not_accepted',
)
return val

View File

@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.17 on 2019-02-08 15:35
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('dav_events', '0027_auto_20190207_1553'),
]
operations = [
migrations.CreateModel(
name='Registration',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True)),
('personal_names', models.CharField(max_length=1024, verbose_name='Vorname(n)')),
('family_names', models.CharField(max_length=1024, verbose_name='Familienname')),
('address', models.CharField(help_text='Stra\xdfe, Hausnummer', max_length=1024, verbose_name='Anschrift')),
('postal_code', models.CharField(max_length=254, verbose_name='Postleitzahl')),
('city', models.CharField(max_length=1024, verbose_name='Ort')),
('email_address', models.EmailField(max_length=254, verbose_name='E-Mail-Adresse')),
('phone_number', models.CharField(help_text='Idealerweise eine Mobilfunk-Nummer', max_length=254, verbose_name='Telefonnummer')),
('dav_number', models.CharField(help_text='Deine Mitgliedsnummer findest du unter dem Strichcode auf deinem DAV Ausweis.<br /> Beispiel: <tt>131/00/012345</tt> (der Teil bis zum ersten * gen\xfcgt)', max_length=62, validators=[django.core.validators.RegexValidator(b'^([0-9]{1,10}/[0-9]{2,10}/)?[0-9]{1,10}(\\*[0-9]{1,10})?(\\*[0-9]{4}\\*[0-9]{4})?([* ][0-9]{8})?$', 'Ung\xfcltiges Format.')], verbose_name='DAV Mitgliednummer')),
('emergency_contact', models.TextField(blank=True, help_text='Name und Telefonnummer bzw. Anschrift, die in Notf\xe4llen informiert werden soll.', verbose_name='Notfall-Kontakt')),
('experience', models.TextField(blank=True, help_text='Welche Touren oder Kurse hast du bereits gemacht?', verbose_name='Erfahrung')),
('note', models.TextField(blank=True, help_text='Wissenswertes f\xfcr den Tourenleiter, z.B. Allergien, gesundheitliche Einschr\xe4nkungen, ...<br /> Kann frei gelassen werden.', verbose_name='Anmerkung')),
('privacy_policy', models.TextField(blank=True, verbose_name='Erkl\xe4rung zur Datenspeicherung')),
('privacy_policy_accepted', models.BooleanField(default=False, verbose_name='Einwilligung zur Datenspeicherung')),
('purge_at', models.DateTimeField()),
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='registrations', to='dav_events.Event')),
],
options={
'ordering': ['created_at'],
'verbose_name': 'Anmeldung',
'verbose_name_plural': 'Anmeldungen',
},
),
]

View File

111
dav_registration/models.py Normal file
View File

@@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
import datetime
import logging
from django.db import models
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from dav_events.models.event import Event
from . import signals
from .validators import DAVNumberValidator
logger = logging.getLogger(__name__)
midnight = datetime.time(00, 00, 00)
one_day = datetime.timedelta(1)
class Registration(models.Model):
event = models.ForeignKey(Event, related_name='registrations')
created_at = models.DateTimeField(auto_now_add=True)
personal_names = models.CharField(max_length=1024,
verbose_name=_(u'Vorname(n)'))
family_names = models.CharField(max_length=1024,
verbose_name=_(u'Familienname'))
address = models.CharField(max_length=1024,
verbose_name=_(u'Anschrift'),
help_text=_(u'Straße, Hausnummer'))
postal_code = models.CharField(max_length=254,
verbose_name=_(u'Postleitzahl'))
city = models.CharField(max_length=1024,
verbose_name=_(u'Ort'))
email_address = models.EmailField(verbose_name=_(u'E-Mail-Adresse'))
phone_number = models.CharField(max_length=254,
verbose_name=_(u'Telefonnummer'),
help_text=_(u'Idealerweise eine Mobilfunk-Nummer'))
dav_number = models.CharField(max_length=62,
validators=[DAVNumberValidator],
verbose_name=_(u'DAV Mitgliednummer'),
help_text=u'%s<br /> %s %s' % (
_(u'Deine Mitgliedsnummer findest du unter dem Strichcode'
u' auf deinem DAV Ausweis.'),
_(u'Beispiel: <tt>131/00/012345</tt>'),
_(u'(der Teil bis zum ersten * genügt)'),
))
emergency_contact = models.TextField(blank=True,
verbose_name=_(u'Notfall-Kontakt'),
help_text=_(u'Name und Telefonnummer bzw. Anschrift,'
u' die in Notfällen informiert werden soll.'))
experience = models.TextField(blank=True,
verbose_name=_(u'Erfahrung'),
help_text=_(u'Welche Touren oder Kurse hast du bereits gemacht?'))
note = models.TextField(blank=True,
verbose_name=_(u'Anmerkung'),
help_text=u'%s<br /> %s' % (
_(u'Wissenswertes für den Tourenleiter, z.B. Allergien,'
u' gesundheitliche Einschränkungen, ...'),
_(u'Kann frei gelassen werden.'))
)
privacy_policy = models.TextField(blank=True,
verbose_name=_(u'Erklärung zur Datenspeicherung'))
privacy_policy_accepted = models.BooleanField(default=False,
verbose_name=_(u'Einwilligung zur Datenspeicherung'))
purge_at = models.DateTimeField()
class Meta:
verbose_name = _(u'Anmeldung')
verbose_name_plural = _(u'Anmeldungen')
ordering = ['created_at']
def __unicode__(self):
return u'{number} - {name} ({created} - {purge})'.format(number=self.event.get_number(),
name=self.get_full_name(),
created=self.created_at.strftime('%d.%m.%Y %H:%M'),
purge=self.purge_at.strftime('%d.%m.%Y %H:%M'))
def get_absolute_url(self):
return reverse('dav_registration:registered')
def get_full_name(self):
return u'{} {}'.format(self.personal_names, self.family_names)
def save(self, **kwargs):
creating = False
if not self.id:
creating = True
if self.event:
self.purge_at = self.__class__.calc_purge_at(self.event)
super(Registration, self).save(**kwargs)
if creating:
logger.info('Registration stored: %s', self)
signals.registration_created.send(sender=self.__class__, registration=self)
@classmethod
def calc_purge_at(cls, event):
if event.alt_last_day:
last_day = event.alt_last_day
elif event.last_day:
last_day = event.last_day
elif event.alt_first_day:
last_day = event.alt_fisrt_day
else:
last_day = event.first_day
return timezone.make_aware(datetime.datetime.combine(last_day + one_day * 7, midnight))

View File

@@ -0,0 +1,3 @@
{
"url_prefix": "registration"
}

View File

@@ -0,0 +1,20 @@
from django.dispatch import Signal
from . import emails
registration_created = Signal(providing_args=['registration'])
def send_emails_on_registration(sender, **kwargs):
registration = kwargs.get('registration')
# Inform the event owner (trainer)
recipient = registration.event.owner
email = emails.InformTrainerRegistrationMail(recipient=recipient, registration=registration)
email.send()
# Inform the potential participant
recipient = u'"{fullname}" <{email}>'.format(fullname=registration.get_full_name(),
email=registration.email_address)
email = emails.InformSelfRegistrationMail(recipient=recipient, registration=registration)
email.send()

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg baseProfile="full" version="1.1" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><g transform="scale(.75)"><svg width="26.667" height="26.667" version="1.1" viewBox="0 0 26.666668 26.666668" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 0 26.667)"><path d="m0 0h20v20h-20z" fill="#2e6876"/></g></svg></g><svg width="20px" height="20px" version="1.1" viewBox="0 0 60.0 60.0" xmlns="http://www.w3.org/2000/svg"><svg width="60" height="60" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg"><g data-name="main"><path d="M54.58105,35.81348l-6.76123,4.83007-3.89111,9.72754A1.00008,1.00008,0,0,1,42.293,50.707L37.499,45.91309l-7.8374-1.74121L26.19775,54.48535a1.00181,1.00181,0,0,1-1.23437.63965l-6.9082-2.06445L6.38477,57.92285a.99985.99985,0,0,1-.76954-1.8457l12-5a.99828.99828,0,0,1,.67139-.03516l6.32324,1.88965,3.44239-10.25a1.00227,1.00227,0,0,1,1.16455-.6582l9,2a1.00193,1.00193,0,0,1,.49023.26953l3.92774,3.92773,3.43652-8.59179a1.00217,1.00217,0,0,1,.34766-.44239l7-5a.99968.99968,0,1,1,1.1621,1.627ZM36.7876,29.16211l-7-3A1.98455,1.98455,0,0,0,29,26H25a1.99957,1.99957,0,0,0-1.96094,1.60742l-1.95654,9.7832L17.17236,46.1875a2.00011,2.00011,0,1,0,3.65528,1.625l4-9a1.98243,1.98243,0,0,0,.1333-.41992L26.63965,30h1.94971l5.56835,2.38672.85791,6.86133a1.99982,1.99982,0,1,0,3.96876-.4961l-1-8A1.99759,1.99759,0,0,0,36.7876,29.16211ZM26.57605,12.05084c-.006.01917-.018.03516-.02332.05463l-3,11A1.50062,1.50062,0,0,0,25,25h3.5a1.50017,1.50017,0,0,0,1.45508-1.13574l1.90588-7.6236,3.12537,2.86481a1.49216,1.49216,0,0,0,.82763.38281l8,1a1.5305,1.5305,0,0,0,.188.01172,1.49993,1.49993,0,0,0,.18409-2.98828l-7.5254-.94043-5.647-5.17676A1.49894,1.49894,0,0,0,30,11H28a1.5015,1.5015,0,0,0-.31287.03369l-.006.00049c-.00873.00189-.016.007-.02466.009a1.48008,1.48008,0,0,0-.31811.11689c-.02966.01464-.05768.03021-.08618.04675a1.4944,1.4944,0,0,0-.246.17737c-.0158.0141-.0335.02545-.0487.04022a1.50273,1.50273,0,0,0-.22449.27966c-.01538.02448-.02722.05054-.04126.076A1.481,1.481,0,0,0,26.57605,12.05084ZM30.99951,10A3.5,3.5,0,1,0,27.5,6.5,3.49935,3.49935,0,0,0,30.99951,10ZM6,42.5a.49008.49008,0,0,0,.14355-.02148c.415-.124,10.22217-3.12989,15.26416-10.20606a.5.5,0,0,0-.81445-.58008c-4.83984,6.792-14.63867,9.79883-14.7373,9.8291A.49984.49984,0,0,0,6,42.5ZM17.44531,20.832l3,2a.99994.99994,0,0,0,1.51953-.56933l3-11a.99881.99881,0,0,0-.64843-1.21094l-3-1a.98968.98968,0,0,0-.77735.06054,1.00223,1.00223,0,0,0-.49707.60059l-3,10A1.00078,1.00078,0,0,0,17.44531,20.832ZM40.02588,23.4082a.49982.49982,0,0,0,.63232.31641A16.55006,16.55006,0,0,1,45,23.0321V35a1,1,0,0,0,2,0V23.0321a16.55006,16.55006,0,0,1,4.3418.69251.50028.50028,0,0,0,.3164-.94922,20.9308,20.9308,0,0,0-11.3164,0A.50069.50069,0,0,0,40.02588,23.4082Z" fill="#fff"/></g></svg></svg></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg baseProfile="full" version="1.1" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><g transform="scale(.75)"><svg width="26.667" height="26.667" version="1.1" viewBox="0 0 26.666668 26.666668" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 0 26.667)"><path d="m0 0h20v20h-20z" fill="#35c774"/></g></svg></g><svg width="20px" height="20px" version="1.1" viewBox="0 0 60.0 60.0" xmlns="http://www.w3.org/2000/svg"><svg width="60px" height="60px" enable-background="new 0 0 60 60" version="1.1" viewBox="0 0 60 60" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="m43.895 38.789c-0.98828 0.49316-2.1899 0.09375-2.6836-0.89453l-3.2241-6.4482-7.3545 2.4512c-0.20361 0.068359-0.41748 0.10254-0.63232 0.10254h-3.3604l-1.6787 8.3926c-0.028809 0.14453-0.073242 0.28516-0.1333 0.41992l-4 9c-0.33105 0.74512-1.0625 1.1885-1.8286 1.1885-0.27148 0-0.54736-0.055664-0.81153-0.17383-1.0093-0.44824-1.4639-1.6299-1.0151-2.6396l3.9102-8.7969 1.9565-9.7832c0.18652-0.93457 1.0078-1.6074 1.9609-1.6074h4.6753l8.6924-2.8975c0.94189-0.3125 1.9761 0.1123 2.4214 1.0029l4 8c0.49365 0.98828 0.093262 2.1895-0.89453 2.6836zm-25.648-19.31l6.2512-1.0418-0.98846 8.8963c-0.047363 0.4248 0.088379 0.84863 0.37305 1.166 0.28467 0.31836 0.69092 0.5 1.1177 0.5h4c0.74268 0 1.373-0.54297 1.4834-1.2773l1.5-10c0.0036621-0.024475-4.883e-4 -0.048523 0.0019531-0.072998l6.8257-4.3879c0.20312-0.13086 0.37158-0.30762 0.49121-0.51758l4-7c0.41113-0.71875 0.16113-1.6357-0.55811-2.0469-0.71924-0.41016-1.6353-0.16016-2.0464 0.55859l-3.8179 6.6807-6.3203 4.0635h-3.5596c-0.08252 0-0.16504 0.0068359-0.24658 0.020508l-8.1514 1.3584-4.4497-5.3398c-0.5293-0.63672-1.4756-0.72266-2.1123-0.19238s-0.72266 1.4756-0.19238 2.1123l5 6.001c0.2876 0.3457 0.71143 0.54004 1.1523 0.54004 0.081543 0 0.16406-0.0068359 0.24658-0.020508zm9.7529-5.4795c1.9341 0 3.5005-1.5664 3.5005-3.5s-1.5664-3.5-3.5005-3.5c-1.9331 0-3.4995 1.5664-3.4995 3.5s1.5664 3.5 3.4995 3.5zm1.5005 20.5c-0.27637 0-0.5 0.22363-0.5 0.5v22c0 0.27637 0.22363 0.5 0.5 0.5s0.5-0.22363 0.5-0.5v-22c0-0.27637-0.22363-0.5-0.5-0.5zm1.7305-7.9209c-0.23242 0.14844-0.30029 0.45801-0.15137 0.69043 0.095215 0.14941 0.25684 0.23047 0.42139 0.23047 0.092285 0 0.18555-0.025391 0.26904-0.079102 0.52002-0.33203 12.73-8.2871 12.73-20.421 0-0.27637-0.22363-0.5-0.5-0.5s-0.5 0.22363-0.5 0.5c0 11.581-12.147 19.5-12.27 19.579z" fill="#fff"/>
</svg></svg></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg baseProfile="full" version="1.1" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><g transform="scale(.75)"><svg width="26.667" height="26.667" version="1.1" viewBox="0 0 26.666668 26.666668" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 0 26.667)"><path d="m0 0h20v20h-20z" fill="#b33451"/></g></svg></g><svg width="20px" height="20px" version="1.1" viewBox="0 0 60.0 60.0" xmlns="http://www.w3.org/2000/svg"><svg width="60px" height="60px" enable-background="new 0 0 60 60" version="1.1" viewBox="0 0 60 60" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="m37.99 40.801l1 10c0.10986 1.0996-0.69189 2.0791-1.791 2.1895-0.067871 0.006836-0.13525 0.0097657-0.20166 0.0097657-1.0151 0-1.8843-0.76953-1.9878-1.8008l-0.95312-9.5352-4.165-6.6641h-1.0815l-0.81982 8.1992c-0.036621 0.3623-0.17139 0.70898-0.39014 1.001l-6 8c-0.66211 0.88379-1.916 1.0645-2.8003 0.39941-0.8833-0.66211-1.0625-1.916-0.3999-2.7998l5.6655-7.5537 0.94434-9.4453c0.10254-1.022 0.96289-1.8008 1.9902-1.8008h4c0.68945 0 1.3306 0.35547 1.6958 0.93994l5 8.0005c0.16309 0.25977 0.26367 0.55469 0.29443 0.86035zm4.6211-14.045l-6.5298-2.9155-3.7578-7.0459c-0.26074-0.48877-0.76953-0.79395-1.3237-0.79395h-2c-0.37549 0-0.73682 0.14062-1.0137 0.39404l-6 5.5c-0.15674 0.14404-0.28125 0.31934-0.36523 0.51514l-3 7c-0.32617 0.76123 0.026367 1.6431 0.78809 1.9697 0.19238 0.08252 0.39307 0.12158 0.59033 0.12158 0.58154 0 1.1353-0.34082 1.3794-0.90967l2.8726-6.7031 2.0482-1.8776-0.78796 6.3038c-0.053711 0.42676 0.079102 0.85596 0.36377 1.1787s0.69434 0.50732 1.1245 0.50732h3.5c0.75635 0 1.3945-0.56348 1.4883-1.314l0.62231-4.9784 1.0657 1.9984c0.15723 0.29395 0.40771 0.52783 0.7124 0.66357l7 3.125c0.75732 0.33838 1.6431-0.0019531 1.981-0.7583s-0.0014648-1.6436-0.7583-1.981zm-11.112-11.755c1.9341 0 3.5005-1.5664 3.5005-3.5s-1.5664-3.5-3.5005-3.5c-1.9331 0-3.4995 1.5664-3.4995 3.5s1.5664 3.5 3.4995 3.5z" fill="#fff"/>
</svg></svg></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg baseProfile="full" version="1.1" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><g transform="scale(.75)"><svg width="26.667" height="26.667" version="1.1" viewBox="0 0 26.666668 26.666668" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 0 26.667)"><path d="m0 0h20v20h-20z" fill="#8b5831"/></g></svg></g><svg width="20px" height="20px" version="1.1" viewBox="0 0 60.0 60.0" xmlns="http://www.w3.org/2000/svg"><svg width="60px" height="60px" enable-background="new 0 0 60 60" version="1.1" viewBox="0 0 60 60" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path d="m54.64 41.769l-6 5c-0.13135 0.10938-0.28809 0.18262-0.45605 0.21387l-15.844 2.9717-10.861 5.9238c-0.10791 0.058594-0.2251 0.09668-0.34668 0.11328l-15 2c-0.044922 0.0058594-0.089355 0.0087891-0.13379 0.0087891-0.49316 0-0.92285-0.36523-0.98975-0.86816-0.073242-0.54688 0.31152-1.0498 0.85889-1.123l14.816-1.9756 10.837-5.9111c0.092285-0.049805 0.19141-0.085938 0.29492-0.10449l15.744-2.9521 5.7998-4.834c0.42432-0.35352 1.0537-0.29688 1.4082 0.12793 0.35352 0.4248 0.29639 1.0557-0.12793 1.4092zm-36.383-10.911l8.8872 3.5547 0.86768 7.8086c0.11377 1.0234 0.97949 1.7793 1.9854 1.7793 0.07373 0 0.14844-0.0039062 0.22314-0.012695 1.0981-0.12109 1.8892-1.1104 1.7671-2.208l-1-9c-0.081543-0.7334-0.56006-1.3623-1.2451-1.6367l-10-4c-1.0239-0.40723-2.189 0.088867-2.5996 1.1143-0.41016 1.0264 0.088379 2.1895 1.1143 2.6006zm2.1855-4.9648l2.5 1c0.18213 0.073242 0.37061 0.10742 0.55664 0.10742 0.54102 0 1.0591-0.29395 1.3262-0.79785l3.2247-6.091 2.6474 4.633c0.27148 0.47559 0.77295 0.75586 1.3022 0.75586 0.12061 0 0.24268-0.014648 0.36377-0.044922l8-2c0.80371-0.20117 1.2925-1.0156 1.0913-1.8193-0.20068-0.80273-1.0156-1.292-1.8188-1.0908l-6.8975 1.7246-3.4365-6.0137c-0.045105-0.078918-0.098511-0.14978-0.15485-0.2171-0.005188-0.0061646-0.0085449-0.013306-0.013794-0.019348-0.12915-0.1496-0.28412-0.26843-0.45441-0.35474-0.0031738-0.0016479-0.0050659-0.0048828-0.0083008-0.0064697l-2-1c-0.70508-0.35352-1.564-0.098633-1.9639 0.58105l-5 8.5c-0.22168 0.37695-0.26807 0.83203-0.12646 1.2461 0.1416 0.41309 0.45654 0.74512 0.8623 0.90723zm9.5566-11.393c1.9341 0 3.5005-1.5663 3.5005-3.5 0-1.9336-1.5664-3.5-3.5005-3.5-1.9331 0-3.4995 1.5664-3.4995 3.5 0 1.9337 1.5664 3.5 3.4995 3.5zm13 11.5c4.9624 0 9 4.0371 9 9s-4.0376 9-9 9-9-4.0371-9-9 4.0376-9 9-9zm-7 9c0 3.8594 3.1401 7 7 7s7-3.1406 7-7-3.1401-7-7-7-7 3.1406-7 7zm-28 9c0-4.9629 4.0376-9 9-9s9 4.0371 9 9-4.0376 9-9 9-9-4.0371-9-9zm2 0c0 3.8594 3.1401 7 7 7s7-3.1406 7-7-3.1401-7-7-7-7 3.1406-7 7z" fill="#fff"/>
</svg></svg></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg baseProfile="full" version="1.1" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><g transform="scale(.75)"><svg width="26.667" height="26.667" version="1.1" viewBox="0 0 26.666668 26.666668" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 0 26.667)"><path d="m0 0h20v20h-20z" fill="#318b74"/></g></svg></g><svg width="20px" height="20px" version="1.1" viewBox="0 0 60.0 60.0" xmlns="http://www.w3.org/2000/svg"><svg width="60" height="60" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg"><g data-name="main"><path d="M54.99365,46.88965a1.00041,1.00041,0,0,1-.8833,1.10449l-8.82275.98047-5.84033,2.91992a1.00525,1.00525,0,0,1-.79834.042l-7.47657-2.80371-8.55859,6.65625a1.002,1.002,0,0,1-.48975.20313l-16,2A1.08944,1.08944,0,0,1,5.99854,58,1,1,0,0,1,5.876,56.00781L21.603,54.042l8.7832-6.831a1.00409,1.00409,0,0,1,.96484-.14746l7.5918,2.84668,5.60986-2.80469a1.01638,1.01638,0,0,1,.33692-.09961l9-1A1.00275,1.00275,0,0,1,54.99365,46.88965ZM29.89453,30.21094A2.00288,2.00288,0,0,0,29,30H25a2.00025,2.00025,0,0,0-1.99023,1.80078L22.042,41.48145l-3.86963,8.706a2.00011,2.00011,0,1,0,3.65528,1.625l4-9a2.00718,2.00718,0,0,0,.16259-.61328L26.81006,34h1.71777l6.62061,3.31055.86718,6.9375a1.99982,1.99982,0,1,0,3.96876-.4961l-1-8a2.00049,2.00049,0,0,0-1.08985-1.541Zm1.03674-14.14655a1.49427,1.49427,0,0,0-.18078-.3822c-.01807-.02765-.038-.05212-.0578-.07837-.02881-.03839-.05268-.07977-.08527-.11554a1.49076,1.49076,0,0,0-.17413-.15454c-.01508-.012-.02735-.02649-.04279-.038a1.49245,1.49245,0,0,0-.36743-.19464c-.03131-.01172-.06225-.02082-.09442-.03046A1.4867,1.4867,0,0,0,29.5,15H27a1.48456,1.48456,0,0,0-.47791.085c-.0202.00684-.04058.01111-.06036.01874a1.48792,1.48792,0,0,0-.3869.22382c-.02118.01666-.04108.03277-.06128.05059a1.49905,1.49905,0,0,0-.287.33783c-.01251.02027-.02222.04126-.03375.0622a1.47782,1.47782,0,0,0-.16467.44348l-.00367.00977-2,11A1.49965,1.49965,0,0,0,25,29h3.5a1.49965,1.49965,0,0,0,1.49365-1.36426l.29657-3.26214a1.49527,1.49527,0,0,0,.27277.2973l5,4a1.49966,1.49966,0,1,0,1.874-2.3418l-4.626-3.70117-1.86866-6.54C30.93994,16.07935,30.93384,16.07288,30.93127,16.06439ZM28.99951,14A3.5,3.5,0,1,0,25.5,10.5,3.49935,3.49935,0,0,0,28.99951,14ZM17.44531,24.832l3,2a.99989.99989,0,0,0,1.53516-.63574l2-10A1,1,0,0,0,23,15H20a1.00016,1.00016,0,0,0-.97021.75781l-2,8A1,1,0,0,0,17.44531,24.832Z" fill="#fff"/></g></svg></svg></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg baseProfile="full" version="1.1" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><g transform="scale(.75)"><svg width="26.667" height="26.667" version="1.1" viewBox="0 0 26.666668 26.666668" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 0 26.667)"><path d="m0 0h20v20h-20z" fill="#2e5676"/></g></svg></g><svg width="20px" height="20px" version="1.1" viewBox="0 0 60.0 60.0" xmlns="http://www.w3.org/2000/svg"><svg width="60" height="60" data-name="main" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg"><path d="M43.5067,37.918l3-18a.49994.49994,0,1,1,.98633.16406l-3,18a.49942.49942,0,0,1-.49268.418.47445.47445,0,0,1-.08252-.00684A.49954.49954,0,0,1,43.5067,37.918Zm-25.083-7.65332a.49967.49967,0,1,0-.84766-.5293l-10,16a.49967.49967,0,1,0,.84766.5293Zm17.377,12.72559a1.99875,1.99875,0,0,0,2.18945-1.791l1-10a2.00114,2.00114,0,0,0-1.57129-2.15527l-7-1.5a2.0049,2.0049,0,0,0-.74756-.0166l-3,.5a1.99922,1.99922,0,0,0-1.62354,1.53906l-1.95508,8.7959L18.17906,49.17285a1.99987,1.99987,0,1,0,3.6416,1.6543l5-11a1.98206,1.98206,0,0,0,.13135-.39355L28.65953,31.751l1.29346-.21582,4.87891,1.0459-.82227,8.21973A2.00027,2.00027,0,0,0,35.80064,42.99023ZM33.49937,12a3.5,3.5,0,1,0-3.49951-3.5A3.49934,3.49934,0,0,0,33.49937,12Zm3.64111,34.93164a.5012.5012,0,0,0-.64209.29492c-.644,1.74023-1.394,2.09863-5.30713,3.33008L8.76451,57.03906a.5.5,0,0,0,.13867.98047A.48775.48775,0,0,0,9.04185,58l22.438-6.48633c3.95166-1.24316,5.12793-1.70117,5.95605-3.93945A.49926.49926,0,0,0,37.14049,46.93164ZM49.1732,38.53125a.50021.50021,0,0,0-.64209.29492c-.67822,1.833-.93164,2.51855-4.665,3.69238l-18,5a.4998.4998,0,0,0,.1333.98145.49191.49191,0,0,0,.13428-.01855l18.01611-5.00488c4.05566-1.27441,4.53516-2.18457,5.31885-4.30273A.49926.49926,0,0,0,49.1732,38.53125ZM18.329,28.3418a1.50069,1.50069,0,0,0,2.0127-.6709l3.81592-7.63184,3.36713-2.16467L25.5526,25.10547a1.49962,1.49962,0,0,0,1.69385,1.874l3-.5a1.49968,1.49968,0,0,0,1.23047-1.21875l1.39825-7.92352,4.111,3.76825a1.50031,1.50031,0,0,0,1.42578.33691l7-2a1.5001,1.5001,0,0,0-.82422-2.88477l-6.19287,1.76953-5.38135-4.93262A1.499,1.499,0,0,0,31.99986,13h-2c-.03271,0-.06335.00757-.09552.00964a1.47453,1.47453,0,0,0-.17694.01636l-.00879.00037-.00812.00281c-.04407.00861-.085.02448-.12756.03687a1.44724,1.44724,0,0,0-.14429.04486c-.02826.01147-.05444.026-.08179.03906-.029.01385-.05573.02972-.08368.04529-.02777.0155-.05719.02557-.08435.043l-7,4.5a1.49572,1.49572,0,0,0-.53076.59082l-4,8A1.50093,1.50093,0,0,0,18.329,28.3418Z" fill="#fff"/></svg></svg></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg baseProfile="full" version="1.1" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><g transform="scale(.75)"><svg width="26.667" height="26.667" version="1.1" viewBox="0 0 26.666668 26.666668" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 0 26.667)"><path d="m0 0h20v20h-20z" fill="#326f9e"/></g></svg></g><svg width="20px" height="20px" version="1.1" viewBox="0 0 60.0 60.0" xmlns="http://www.w3.org/2000/svg"><svg width="60" height="60" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg"><g data-name="main"><path d="M36.12451,37.23145,30.46875,34H28.81006l-.81983,8.19922a2.00725,2.00725,0,0,1-.39013,1.001l-6,8a2.0002,2.0002,0,0,1-3.2002-2.4004l5.66553-7.55371.94434-9.44531A2.00025,2.00025,0,0,1,27,30h4a1.998,1.998,0,0,1,.99219.26367l7,4a1.99974,1.99974,0,0,1,.9956,1.51563l1,9a2,2,0,0,1-3.97558.4414ZM19.40918,30.37891a1.50064,1.50064,0,0,0,1.96973-.78809l2.87255-6.70312,2.04816-1.87751-.7879,6.30329A1.49931,1.49931,0,0,0,27,29h3.5a1.5,1.5,0,0,0,1.48828-1.31348l.87024-6.96167L35.898,24.01758a1.49715,1.49715,0,0,0,.49072.35254l7,3.125a1.50032,1.50032,0,0,0,1.22266-2.74024l-6.71826-2.999-5.791-6.27344A1.49938,1.49938,0,0,0,31,15H29a1.49894,1.49894,0,0,0-1.01367.39453l-6,5.5a1.50372,1.50372,0,0,0-.36524.51465l-3,7A1.5,1.5,0,0,0,19.40918,30.37891ZM31.49951,14A3.5,3.5,0,1,0,28,10.5,3.49935,3.49935,0,0,0,31.49951,14ZM44.96436,42.499c.0122.001.02441.001.03613.001a.5.5,0,0,0,.498-.46484l1-14a.49942.49942,0,0,0-.4629-.53418.49326.49326,0,0,0-.53418.46386l-1,14A.49942.49942,0,0,0,44.96436,42.499ZM18.7998,31.59961a.5014.5014,0,0,0-.6997.10059l-10.5,14a.4998.4998,0,1,0,.7998.5996l10.5-14A.49976.49976,0,0,0,18.7998,31.59961ZM44.293,46.293,42.54541,48.04l-9.645.96484A1,1,0,0,0,32.999,51c.03321,0,.0669-.002.10059-.00488l10-1A1.00323,1.00323,0,0,0,43.707,49.707l2-2A.99989.99989,0,0,0,44.293,46.293Zm-19,5L23.58594,53H14a1,1,0,0,0,0,2H24a1.00012,1.00012,0,0,0,.707-.293l2-2A.99989.99989,0,0,0,25.293,51.293Z" fill="#fff"/></g></svg></svg></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg baseProfile="full" version="1.1" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><g transform="scale(.75)"><svg width="26.667" height="26.667" version="1.1" viewBox="0 0 26.666668 26.666668" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 0 26.667)"><path d="m0 0h20v20h-20z" fill="#329e60"/></g></svg></g><svg width="20px" height="20px" version="1.1" viewBox="0 0 60.0 60.0" xmlns="http://www.w3.org/2000/svg"><svg width="60" height="60" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg"><g data-name="main"><path d="M46.71777,4.13379A1.99806,1.99806,0,0,0,44.1333,5.28223L42.56873,9.35016,39.67151,8.19128l.81872-4.09362a.49953.49953,0,0,0-.39209-.58789.49421.49421,0,0,0-.58837.39257l-.98926,4.94532-4.0083,9.042L29.502,39.95508l-1,11a.49859.49859,0,0,0,.00782.14258l1,5a.49973.49973,0,0,0,.48974.40234.4891.4891,0,0,0,.09863-.00977.49953.49953,0,0,0,.39209-.58789L29.70984,52h3.51507l.87763,2.63281a2.0002,2.0002,0,0,0,3.79492-1.26562l-.86133-2.583.91211-8.209,3.84082-7.68067a1.9978,1.9978,0,0,0,.20655-.76172l.98-14.69726L47.8667,6.71777A1.999,1.999,0,0,0,46.71777,4.13379ZM29.59247,50l.79815-8.8161,3.556,1.18536L33.09882,50Zm4.94232-9.54211L30.699,39.17926l4.56421-20.12164,3.68756.61456-.91949,13.79364Zm4.81793-22.74616-3.42364-.57062,3.12909-7.04052,2.79229,1.11694ZM28.48486,36.94043a2.00116,2.00116,0,0,1-2.42529-1.45508l-1.395-5.581-5.77,2.88476a1.99472,1.99472,0,0,1-.19336.084l4.71289,4.71289a2.00438,2.00438,0,0,1,.41358.60156l4,9a2.00011,2.00011,0,1,1-3.65528,1.625l-3.84912-8.66113-6.7373-6.73731a1.99993,1.99993,0,0,1,.78174-3.31152l2.86523-.95508,7.87256-3.93652a1.99989,1.99989,0,0,1,2.835,1.30371l2,8A2.0003,2.0003,0,0,1,28.48486,36.94043ZM14,29a1.50052,1.50052,0,0,1-1.40967-2.0127l4-11c.00269-.00732.00873-.01214.01148-.0194a1.4886,1.4886,0,0,1,.25055-.4231c.01519-.01819.02856-.0365.04449-.05389a1.496,1.496,0,0,1,.36932-.29163c.02088-.01178.04078-.023.0622-.03375a1.47711,1.47711,0,0,1,.44922-.14313c.0249-.00378.04919-.005.0744-.00751A1.4635,1.4635,0,0,1,18,15h3a1.50039,1.50039,0,0,1,.75586.2041l5.19141,3.02832L32.168,14.752a1.5,1.5,0,0,1,1.66406,2.4961l-6,4a1.50068,1.50068,0,0,1-1.58789.04785l-5.09009-2.96936-2.72387,8.62561a1.49752,1.49752,0,0,1-.95606.9707l-3,1A1.4991,1.4991,0,0,1,14,29Zm4-18.5A3.5,3.5,0,1,1,21.49951,14,3.49914,3.49914,0,0,1,18,10.5Z" fill="#fff"/></g></svg></svg></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,3 @@
{% extends "dav_base/base.html" %}
{% block head-title %}Touren und Kurse - {{ block.super }}{% endblock %}

View File

@@ -0,0 +1,40 @@
Hallo {{ registration.get_full_name }},
wir haben deine Anmeldung zur Veranstaltung
{{ event.number }} - {{ event.title }}
an den/die Tourenleiter/in {{ event.get_trainer_full_name }} weitergegeben.
{{ event.trainer_firstname }} wird sich bei dir melden und dir mitteilen,
ob du teilnehmen kannst oder nicht.
========================================================================
Veranstaltung: {{ event.number }} - {{ event.title }}
Datum: {{ event.get_formated_date }}
Tourenleitung: {{ event.get_trainer_full_name }}
Anmeldezeitpunkt: {{ registration.created_at|date:'l, d. F Y, G:i' }}
Anmeldenummer: {{ registration.id }}
Personendaten
-------------
{{ registration.get_full_name }}
{{ registration.address }}
{{ registration.postal_code }} {{ registration.city }}
Telefon: {{ registration.phone_number }}
E-Mail: {{ registration.email_address }}
DAV Mitgliedsnummer: {{ registration.dav_number }}
Notfall-Kontakt
---------------
{% if registration.emergency_contact %}{{ registration.emergency_contact }}{% else %}-{% endif %}
Erfahrung
---------
{% if registration.experience %}{{ registration.experience }}{% else %}-{% endif %}
Anmerkung
---------
{% if registration.note %}{{ registration.note }}{% else %}-{% endif %}
Erklärung zur Datenspeicherung
------------------------------
{% if registration.privacy_policy %}{{ registration.privacy_policy }}{% else %}-{% endif %}
Zeitpunkt der Datenlöschung: {{ registration.purge_at|date:'l, d. F Y' }}

View File

@@ -0,0 +1,42 @@
Hallo {{ recipient.first_name }},
Anmeldung zu deiner Veranstaltung {{ event.number }}
{{ event.title }}
========================================================================
Anmeldezeitpunkt: {{ registration.created_at|date:'l, d. F Y, G:i' }}
Anmeldenummer: {{ registration.id }}
Teilnehmer*in
-------------
{{ registration.get_full_name }}
Telefonnummer und E-Mail-Adresse
--------------------------------
{{ registration.phone_number }}
{{ registration.email_address }}
Erfahrung
---------
{% if registration.experience %}{{ registration.experience }}{% else %}-{% endif %}
Anmerkung
---------
{% if registration.note %}{{ registration.note }}{% else %}-{% endif %}
Personendaten
-------------
{{ registration.get_full_name }}
{{ registration.address }}
{{ registration.postal_code }} {{ registration.city }}
Telefon: {{ registration.phone_number }}
E-Mail: {{ registration.email_address }}
DAV Mitgliedsnummer: {{ registration.dav_number }}
Notfall-Kontakt
---------------
{% if registration.emergency_contact %}{{ registration.emergency_contact }}{% else %}-{% endif %}
Erklärung zur Datenspeicherung
------------------------------
{% if registration.privacy_policy %}{{ registration.privacy_policy }}{% else %}-{% endif %}
Zeitpunkt der Datenlöschung: {{ registration.purge_at|date:'l, d. F Y' }}

View File

@@ -0,0 +1,119 @@
{% load i18n %}
{% if event.requirements %}
<strong>{% trans 'Anforderungen' %}:</strong> {{ event.requirements }}<br />
{% endif %}
{% if event.equipment %}
<strong>{% trans 'Ausrüstung' %}:</strong> {{ event.equipment }}<br />
{% endif %}
{% if event.location %}
<strong>{% trans 'Ort' %}:</strong> {{ event.location }}
{% if event.country and event.country != 'DE' and event.country != 'XX' %}({{ event.country }}){% endif %}<br />
{% endif %}
{% if event.basecamp %}
<strong>{% trans 'Stützpunkt' %}:</strong> {{ event.basecamp }}<br />
{% endif %}
{% if event.accommodation and event.accommodation != 'NONE' %}
<strong>{% trans 'Unterkunft' %}:</strong>
{% if event.accommodation == 'OTHER' %}
{{ event.accommodation_other }}
{% else %}
{{ event.get_accommodation_display }}
{% endif %}
<br />
{% endif %}
{% if event.meals and event.meals != 'NONE' %}
<strong>{% trans 'Verpflegung' %}:</strong>
{% if event.meals == 'OTHER' %}
{{ event.meals_other }}
{% else %}
{{ event.get_meals_display }}
{% endif %}
<br />
{% endif %}
{% if event.transport and event.transport != 'NONE' and event.transport != 'public' %}
<strong>{% trans 'Hin- / Rückfahrt' %}:</strong>
{% if event.transport == 'OTHER' %}
{{ event.transport_other }}
{% else %}
{{ event.get_transport_display }}
{% endif %}
<br />
{% endif %}
{% if event.meeting_point and event.meeting_point != 'NONE' %}
<strong>{% trans 'Treffpunkt' %}:</strong>
{% if event.meeting_time %}
{{ event.meeting_time|time:'G:i'|cut:':00' }} Uhr,
{% endif %}
{% if event.meeting_point == 'OTHER' %}
{{ event.meeting_point_other }}
{% else %}
{{ event.get_meeting_point_display }}
{% endif %}
<br />
{% endif %}
{% if event.transport == 'public' %}
{% if event.departure_time or event.departure_ride %}
<strong>{% trans 'Abfahrt' %}:</strong>
{% if event.departure_time %}{{ event.departure_time|time:'G:i'|cut:':00' }} Uhr{% endif %}{% if event.departure_time and event.departure_ride %}, {% endif %}{%if event.departure_ride %}{{ event.departure_ride }}{% endif %}
<br />
{% endif %}
{% endif %}
{% if event.return_departure_time or event.return_arrival_time %}
<strong>{% trans 'Rückfahrt' %}:</strong>
{% if event.return_arrival_time %}{{ event.return_arrival_time|time:'G:i'|cut:':00' }} Uhr ({% trans 'Ankunft in' %} Karlsruhe)
{% elif event.return_departure_time %}{{ event.return_departure_time|time:'G:i'|cut:':00' }} Uhr ({% trans 'Abfahrt am Tourenort' %})
{% endif %}
<br />
{% endif %}
{% if event.pre_meeting_1 %}
{% if event.pre_meeting_2 %}
<strong>{% trans 'Vortreffen' %} 1:</strong> {{ event.pre_meeting_1|date:'l, d. F Y, G:i'|cut:':00' }} {% trans 'Uhr' %}, DAV {% trans 'Sektionszentrum' %}<br />
<strong>{% trans 'Vortreffen' %} 2:</strong> {{ event.pre_meeting_2|date:'l, d. F Y, G:i'|cut:':00' }} {% trans 'Uhr' %}, DAV {% trans 'Sektionszentrum' %}<br />
{% else %}
<strong>{% trans 'Vortreffen' %}:</strong> {{ event.pre_meeting_1|date:'l, d. F Y, G:i'|cut:':00' }} {% trans 'Uhr' %}, DAV {% trans 'Sektionszentrum' %}<br />
{% endif %}
{% endif %}
{% if event.min_participants > 0 or event.max_participants > 0 %}
<strong>{% trans 'Teilnehmerzahl' %}:</strong>
{% if event.min_participants == event.max_participants %}
{{ event.max_participants }} {% trans 'Teilnehmer' %}
{% elif event.min_participants > 0 and event.max_participants > 0 %}
{{ event.min_participants }} - {{ event.max_participants }} {% trans 'Teilnehmer' %}
{% elif event.min_participants > 0 %}
min. {{ event.min_participants }} {% trans 'Teilnehmer' %}
{% else %}
max. {{ event.max_participants }} {% trans 'Teilnehmer' %}
{% endif %}
<br />
{% endif %}
{% if event.charge > 0 or event.additional_costs %}
<strong>{% trans 'Kosten' %}:</strong>
{% if event.charge > 0 %}
{{ event.charge|floatformat:'-2' }} € {% trans 'Teilnahmegebühr' %}
{% endif %}
{% if event.additional_costs %}
{% if event.charge > 0 %}{% trans 'zzgl.' %}{% endif %}
{{ event.additional_costs }}
{% endif %}
<br />
{% endif %}
{% if event.registration_required and event.deadline %}<strong>{% trans 'Anmeldeschluss' %}:</strong> {{ event.deadline|date:'l, d. F Y' }}<br />{% endif %}
{% if event.trainer_2_fullname %}
{% if event.mode == 'training' %}
<strong>{% trans 'Ausbildungsteam' %}:</strong>
{% else %}
<strong>{% trans 'Team' %}:</strong>
{% endif %}
{{ event.trainer_firstname }} {{ event.trainer_familyname }},
{{ event.trainer_2_fullname }}{% if event.trainer_3_fullname %},
{{ event.trainer_3_fullname }}{% endif %}
<br />
{% endif %}
{% if event.trainer_familyname %}
<strong>{% trans 'Leitung' %}:</strong>
{{ event.trainer_firstname }} {{ event.trainer_familyname }}
{% if event.trainer_email or event.trainer_phone %}
({% if event.trainer_email %}<a href="mailto:{{ event.trainer_email }}">{{ event.trainer_email }}</a>{% endif %}{% if event.trainer_email and event.trainer_phone %}, {% endif %}{% if event.trainer_phone %}{{ event.trainer_phone }}{% endif %})
{% endif %}
{% endif %}

View File

@@ -0,0 +1,52 @@
{% load i18n %}
<p>
<em>{{ event.description|urlize|linebreaksbr }}</em>
</p>
{% if event.mode == 'training' %}
<div>
<p><strong>{% trans 'Kursinhalte' %}:</strong></p>
{% if event.course_topic_2 %}
<ul>
<li>{{ event.course_topic_1|urlize }}</li>
<li>{{ event.course_topic_2|urlize }}</li>
{% if event.course_topic_3 %}
<li>{{ event.course_topic_3|urlize }}</li>
{% endif %}
{% if event.course_topic_4 %}
<li>{{ event.course_topic_4|urlize }}</li>
{% endif %}
{% if event.course_topic_5 %}
<li>{{ event.course_topic_5|urlize }}</li>
{% endif %}
{% if event.course_topic_6 %}
<li>{{ event.course_topic_6|urlize }}</li>
{% endif %}
</ul>
{% else %}
<p>{{ event.course_topic_1|urlize|linebreaksbr }}</p>
{% endif %}
</div>
<div>
<p><strong>{% trans 'Kursziele' %}:</strong></p>
{% if event.course_goal_2 %}
<ul>
<li>{{ event.course_goal_1|urlize }}</li>
<li>{{ event.course_goal_2|urlize }}</li>
{% if event.course_goal_3 %}
<li>{{ event.course_goal_3|urlize }}</li>
{% endif %}
{% if event.course_goal_4 %}
<li>{{ event.course_goal_4|urlize }}</li>
{% endif %}
{% if event.course_goal_5 %}
<li>{{ event.course_goal_5|urlize }}</li>
{% endif %}
{% if event.course_goal_6 %}
<li>{{ event.course_goal_6|urlize }}</li>
{% endif %}
</ul>
{% else %}
<p>{{ event.course_goal_1|urlize|linebreaksbr }}</p>
{% endif %}
</div>
{% endif %}

View File

@@ -0,0 +1,36 @@
{% extends 'dav_registration/base.html' %}
{% load i18n %}
{% load dav_registration %}
{% block head-title %}{{ event.number }} - {{ block.super }}{% endblock head-title %}
{% block page-container-fluid %}
<div class="row">
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<span class="panel-title">{{ event.number }} - {{ event.title }}</span>
</div>
<ul class="list-group">
<li class="list-group-item">
<strong>{{ event.get_formated_date }}</strong>
{% if event.get_alt_formated_date %}
<br />
<strong>({% trans 'Ersatztermin' %}: {{ event.get_alt_formated_date }})</strong>
{% endif %}
</li>
<li class="list-group-item">
{% render_event_paragraphs event %}
</li>
<li class="list-group-item">
{% render_event_facts event %}
</li>
<li class="list-group-item">
<a class="btn btn-primary" href="{% url 'dav_registration:register' event.pk %}">{% trans 'Anmelden' %}</a>
<a class="btn btn-danger" href="{% url 'dav_registration:events' %}">{% trans 'Zurück' %}</a>
</li>
</ul>
</div>
</div>
</div>
{% endblock page-container-fluid %}

View File

@@ -0,0 +1,103 @@
{% extends 'dav_registration/base.html' %}
{% load static %}
{% load i18n %}
{% load dav_registration %}
{% block page-container-fluid %}
<div>
<h3>Touren & Kurse</h3>
<table id="objects_table" class="table table-bordered table-hover">
<thead>
<tr>
<th><input type="text" id="searchfield" placeholder="{% trans 'Suche' %}"></th>
</tr>
</thead>
<tbody>
{% for event in event_list %}
<tr>
<td>
<div class="pull-right" style="margin-left: 2em;">
<a role="button" id="controlCollapseDetails{{ event.id }}" data-toggle="collapse"
href="#collapseDetails{{ event.id }}"
aria-expanded="false" aria-controls="collapseDetails{{ event.id }}">
<span title="{% trans 'Details aufklappen' %}" class="glyphicon glyphicon-chevron-down"></span>
</a>
</div>
<div class="pull-right" style="margin-left: 1em;">
<a class="btn btn-primary" href="{% url 'dav_registration:event' event.pk %}">Details & Anmeldung</a>
</div>
<div class="pull-left" style="margin-right: 12px;">
{% with event.sport as sport %}
{% with 'dav_registration/img/sport_icons/'|add:sport|add:'.png' as icon %}
<img src="{% static icon %}" width="48px"
alt="{{ event.get_sport_display }}" title="{{ event.get_sport_display }}">
<span class="hidden">{{ event.get_sport_display }}</span>
{% endwith %}
{% endwith %}
</div>
<div>
<strong>
{{ event.get_number }} - {{ event.title }}
</strong>
<p>
{{ event.get_formated_date }}
{% if event.get_alt_formated_date %}
<br />({% trans 'Ersatztermin' %}: {{ event.get_alt_formated_date }})
{% endif %}
</p>
<div class="panel panel-default collapse" id="collapseDetails{{ event.id }}" style="margin-top: 2ex;">
<ul class="list-group">
<li class="list-group-item">
{% render_event_paragraphs event %}
</li>
<li class="list-group-item">
{% render_event_facts event %}
</li>
<li class="list-group-item">
<a class="btn btn-primary" href="{% url 'dav_registration:event' event.pk %}">zur Anmeldung</a>
</li>
</ul>
</div>
</div>
<script>
$("#collapseDetails{{ event.id }}").on("shown.bs.collapse", function() {
icon = $("#controlCollapseDetails{{ event.id }}").find(".glyphicon")
icon.removeClass("glyphicon-chevron-down").addClass("glyphicon-chevron-up");
icon.attr("title", "{% trans 'Details verbergen' %}");
});
$("#collapseDetails{{ event.id }}").on("hidden.bs.collapse", function() {
icon = $("#controlCollapseDetails{{ event.id }}").find(".glyphicon")
icon.removeClass("glyphicon-chevron-up").addClass("glyphicon-chevron-down");
icon.attr("title", "{% trans 'Details aufklappen' %}");
});
</script>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<script type="text/javascript">
$(document).ready( function () {
var table = $("#objects_table").DataTable( {
ordering: false,
paging: false,
language: {
search: "{% trans 'Suche' %}:",
info: "{% trans 'Zeige _TOTAL_ Einträge' %}",
infoFiltered: "{% trans 'aus insgesamt _MAX_ Einträgen' %}",
infoEmpty: "{% trans 'Zeige 0 Einträge' %}",
infoPostFix: ".",
emptyTable: "{% trans 'Keine Daten vorhanden.' %}",
zeroRecords: "{% trans 'Keine passenden Einträge.' %}",
}
} );
$("#searchfield").on( "keyup change", function() {
table
.search( this.value )
.draw();
} );
$("#objects_table_filter").hide();
} );
</script>
</div>
{% endblock page-container-fluid %}

View File

@@ -0,0 +1,44 @@
{% extends 'dav_registration/base.html' %}
{% load bootstrap3 %}
{% load i18n %}
{% load dav_registration %}
{% block head-title %}Anmeldung abgeschickt - {{ block.super }}{% endblock head-title %}
{% block page-container-fluid %}
<div class="well">
<p>
Du solltest in Kürze eine E-Mail von uns mit deinen Anmeldedaten erhalten.
</p>
<p>
Diese E-Mail gilt <strong>noch nicht als Zusage</strong> zur Teilnahme.
</p>
<p>
Die Tourenleitung wurde über deine Anmeldung informiert und wird sich bei dir melden.
</p>
</div>
{% if object %}
<div class="panel panel-default">
<div class="panel-heading">
Anmeldung zu <strong>{{ object.event.number }} - {{ object.event.title }}</strong>
</div>
<ul class="list-group">
<li class="list-group-item">Datum: {{ object.event.get_formated_date }}</li>
<li class="list-group-item">Tourenleitung: {{ object.event.get_trainer_full_name }} (<a href="{{ object.event.trainer_email }}">{{ object.event.trainer_email }}</a>)</li>
<li class="list-group-item">Anmeldezeitpunkt: {{ object.created_at|date:'l, d. F Y, G:i' }}</li>
<li class="list-group-item">Anmeldenummer: {{ object.pk }}</li>
<li class="list-group-item">Speicherung bis: {{ object.purge_at|date:'l, d. F Y' }}</li>
<li class="list-group-item">Teilnehmer*in: {{ object.get_full_name }} ({{ object.email_address }})</li>
</ul>
</div>
{% else %}
<div class="alert alert-danger" role="alert">
Äh, ich bin mir gerade nicht sicher, wo ich bin.
Hast du auf <i>Reload</i>, <i>Aktualisieren</i>, <i>Neu laden</i> oder sonst was geklickt?
</div>
{% endif %}
<a class="btn btn-primary" href="{% url 'dav_registration:events' %}">
{% bootstrap_icon 'list' %}&thinsp;
{% trans 'zurück zur Tourenliste' %}
</a>
{% endblock page-container-fluid %}

View File

@@ -0,0 +1,123 @@
{% extends "dav_registration/base.html" %}
{% load bootstrap3 %}
{% load i18n %}
{% block head-title %}{% block form-title %}{% trans 'Anmeldung' %} - {{ event.number }}{% endblock form-title %} - {{ block.super }}{% endblock head-title %}
{% block page-container-fluid %}
<h3>{% trans 'Anmeldung' %}</h3>
<form>
<div class="form-group">
<label class="control-label" for="event">{% trans 'Veranstaltung' %}</label>
<input id="event" class="form-control" type="text" value="{{ event }}" readonly>
</div>
</form>
{% block form-errors %}
{% bootstrap_form_errors form %}
{% endblock form-errors %}
{% block form %}
<form action="" method="post">
{% block form-content %}
{% csrf_token %}
{% block form-fields %}
{% block form-fields-hidden %}
{% for field in form.hidden_fields %}
{{ field }}
{% endfor %}
{% endblock form-fields-hidden %}
{% block form-fields-visible %}
<div class="row">
<div class="col-sm-6">
{% bootstrap_field form.personal_names %}
</div>
<div class="col-sm-6">
{% bootstrap_field form.family_names %}
</div>
</div>
<div class="row">
<div class="col-sm-12">
{% bootstrap_field form.address %}
</div>
</div>
<div class="row">
<div class="col-sm-4">
{% bootstrap_field form.postal_code %}
</div>
<div class="col-sm-8">
{% bootstrap_field form.city %}
</div>
</div>
<div class="row">
<div class="col-sm-6">
{% bootstrap_field form.email_address %}
</div>
<div class="col-sm-6">
{% bootstrap_field form.phone_number %}
</div>
</div>
<div class="row">
<div class="col-sm-6">
{% bootstrap_field form.dav_number %}
</div>
<div class="col-sm-6">
{% bootstrap_field form.emergency_contact %}
</div>
</div>
<div class="row">
<div class="col-sm-6">
{% bootstrap_field form.experience %}
</div>
<div class="col-sm-6">
{% bootstrap_field form.note %}
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label class="control-label" for="privacy_policy">{% trans 'Erklärung zur Datenspeicherung' %}</label>
<div id="privacy_policy" class="well well-sm form-control-static">
<p>
<small>{{ privacy_policy|linebreaksbr }}</small>
</p>
<small>{% trans 'Zeitpunkt der Löschung' %}: {{ purge_at|date:'l, d. F Y' }}</small>
</div>
</div>
{% if form.privacy_policy_accepted.errors %}
<div class="has-error">
{% endif %}
<div class="checkbox">
<label>
<input type="checkbox" name="privacy_policy_accepted" {% if form.privacy_policy_accepted.value %}checked="checked"{% endif %}">
{% trans 'Ich willige in die oben erläuterte Datenspeicherung ein.' %}
</label>
</div>
{% if form.privacy_policy_accepted.errors %}
<div class="help-block">
{% for error in form.privacy_policy_accepted.errors %}
<p>{{ error }}</p>
{% endfor %}
</div>
</div>
{% endif %}
</div>
</div>
{% endblock form-fields-visible %}
{% endblock form-fields %}
<div class="row">&nbsp;</div>
{% block form-buttons %}
{% buttons %}
<button type="submit" class="btn btn-success">
{% bootstrap_icon 'ok' %}&thinsp;
{% trans 'Anmeldung abschicken' %}
</button>
<a class="btn btn-danger" href="{% url 'dav_registration:event' event.pk %}">
{% bootstrap_icon 'remove' %}&thinsp;
{% trans 'Zurück' %}
</a>
{% endbuttons %}
{% endblock form-buttons %}
{% endblock form-content %}
</form>
{% endblock form %}
{% endblock page-container-fluid %}

View File

@@ -0,0 +1,16 @@
from django import template
from django.template.loader import render_to_string
register = template.Library()
@register.simple_tag
def render_event_paragraphs(event):
return render_to_string('dav_registration/event/paragraphs.html', {'event': event})
@register.simple_tag
def render_event_facts(event):
return render_to_string('dav_registration/event/facts.html', {'event': event})

11
dav_registration/urls.py Normal file
View File

@@ -0,0 +1,11 @@
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.RootView.as_view(), name='root'),
url(r'^finished', views.RegistrationSuccessView.as_view(), name='registered'),
url(r'^event/(?P<pk>\d+)/registration', views.RegistrationView.as_view(), name='register'),
url(r'^event/(?P<pk>\d+)/', views.EventDetailView.as_view(), name='event'),
url(r'^event', views.EventListView.as_view(), name='events'),
]

13
dav_registration/utils.py Normal file
View File

@@ -0,0 +1,13 @@
import logging
from django.utils import timezone
from .models import Registration
logger = logging.getLogger(__name__)
def purge_registrations():
now = timezone.now()
for r in Registration.objects.filter(purge_at__lte=now):
logger.info('Purge registration \'%s\'', r)
r.delete()

View File

@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
from django.core.validators import RegexValidator
from django.utils.translation import ugettext_lazy as _
DAVNumberValidator = RegexValidator(r'^'
r'([0-9]{1,10}/[0-9]{2,10}/)?'
r'[0-9]{1,10}'
r'(\*[0-9]{1,10})?'
r'(\*[0-9]{4}\*[0-9]{4})?'
r'([* ][0-9]{8})?'
r'$',
_(u'Ungültiges Format.'))

189
dav_registration/views.py Normal file
View File

@@ -0,0 +1,189 @@
# -*- coding: utf-8 -*-
import datetime
import logging
from django.apps import apps
from django.contrib import messages
from django.db.models import Q
from django.urls import reverse_lazy
from django.utils.translation import ugettext as _
from django.views import generic
from dav_events.models.event import Event
from .forms import RegistrationForm
from .models import Registration
from .utils import purge_registrations
app_config = apps.get_containing_app_config(__package__)
logger = logging.getLogger(__name__)
class RootView(generic.RedirectView):
url = reverse_lazy('dav_registration:events')
def get(self, request, *args, **kwargs):
purge_registrations()
return super(RootView, self).get(request, *args, **kwargs)
class EventListView(generic.ListView):
model = Event
template_name = 'dav_registration/event_list.html'
def get_queryset(self):
today = datetime.date.today()
filter = Q(flags__status__code__in=('publishing', 'publishing_web', 'publishing_facebook',
'published', 'published_web', 'published_facebook'))
filter &= Q(planned_publication_date__isnull=True) | Q(planned_publication_date__lte=today)
filter &= Q(first_day__gte=today)
filter &= Q(deadline__isnull=True) | Q(deadline__gte=today)
qs = self.model.objects.filter(filter).order_by('first_day', 'number').distinct()
return qs
class EventDetailView(generic.DetailView):
model = Event
template_name = 'dav_registration/event_detail.html'
def get_queryset(self):
today = datetime.date.today()
filter = Q(flags__status__code__in=('publishing', 'publishing_web', 'publishing_facebook',
'published', 'published_web', 'published_facebook'))
filter &= Q(planned_publication_date__isnull=True) | Q(planned_publication_date__lte=today)
filter &= Q(first_day__gte=today)
filter &= Q(deadline__isnull=True) | Q(deadline__gte=today)
qs = self.model.objects.filter(filter).distinct()
return qs
class RegistrationView(generic.CreateView):
model = Registration
form_class = RegistrationForm
initial = {
'personal_names': 'Jens',
'family_names': 'Kleineheismann',
'address': 'Marie-Alexandra-Str. 6',
'postal_code': '76135',
'city': 'Karlsruhe',
'email_address': 'heinzel@heinzelwerk.de',
'phone_number': '0178 143 2886',
'note': 'Nur ein Test.',
'dav_number': '131/00/007',
'experience': 'Ich kann alles.',
'privacy_policy_accepted': True,
}
def get_queryset(self):
today = datetime.date.today()
filter = Q(flags__status__code__in=('publishing', 'publishing_web', 'publishing_facebook',
'published', 'published_web', 'published_facebook'))
filter &= Q(planned_publication_date__isnull=True) | Q(planned_publication_date__lte=today)
filter &= Q(first_day__gte=today)
filter &= Q(deadline__isnull=True) | Q(deadline__gte=today)
qs = Event.objects.filter(filter).distinct()
return qs
def get_initial(self):
initials = super(RegistrationView, self).get_initial()
return initials
def get_form(self, form_class=None):
form = super(RegistrationView, self).get_form(form_class)
event = self.get_object()
experience_label = form.fields['experience'].label
experience_help_text = form.fields['experience'].help_text
if event.sport == 'B':
experience_label = _(u'Eigene Bergerfahrung')
elif event.sport == 'K' and event.terrain == 'alpine':
experience_label = _(u'Eigene Fels- und Bergerfahrung')
if event.level == 'beginner':
experience_help_text = u'%s<br /> %s<br /> %s' % (
_(u'Warst du schon mal im Gebirge klettern?'),
_(u'In welchem Schwierigkeitsgrad hast du Spaß?'),
_(u'Bist du schon mal vorgestiegen?')
)
else:
experience_help_text = u'%s<br /> %s<br /> %s' % (
_(u'In welchen Klettergebieten/Touren warst du bisher unterwegs?'),
_(u'In welchem Schwierigkeitsgrad hast du im Vorstieg Spaß?'),
_(u'Wie waren die Touren abgesichert, in denen du dich noch wohlgefühlt hast?')
)
elif event.sport == 'K':
experience_label = _(u'Eigene Klettererfahrung')
if event.level == 'beginner':
experience_help_text = u'%s<br /> %s<br /> %s' % (
_(u'Warst du schon mal am Fels klettern?'),
_(u'In welchem Schwierigkeitsgrad hast du Spaß?'),
_(u'Bist du schon mal vorgestiegen?')
)
else:
experience_help_text = u'%s<br /> %s<br /> %s' % (
_(u'In welchen Klettergebieten warst du bisher unterwegs?'),
_(u'In welchem Schwierigkeitsgrad hast du im Vorstieg Spaß?'),
_(u'Wie waren die Touren abgesichert, in denen du dich noch wohlgefühlt hast?')
)
elif event.sport == 'M':
experience_label = _(u'Eigene MTB-Erfahrung')
experience_help_text = u'%s' % (
_(u'Was für Touren bist du schon gefahren?')
)
if event.level != 'beginner':
experience_help_text += u'<br /> %s' % (
_(u'Single-Trail-Schwierigkeit (S0-S5) bei der du dich wohl fühlst?')
)
elif event.sport == 'S':
experience_label = _(u'Eigene Skitouren- und Bergerfahrung')
elif event.sport == 'W':
experience_help_text += u'<br /> %s' % (
_(u'Kann frei gelassen werden.')
)
form.fields['experience'].label = experience_label
form.fields['experience'].help_text = experience_help_text
form.instance.event = event
form.instance.privacy_policy = app_config.settings.privacy_policy
return form
def get_context_data(self, **kwargs):
context = super(RegistrationView, self).get_context_data(**kwargs)
event = self.get_object()
context['event'] = event
context['privacy_policy'] = app_config.settings.privacy_policy
context['purge_at'] = self.model.calc_purge_at(event)
return context
def form_valid(self, form):
r = super(RegistrationView, self).form_valid(form)
self.request.session['registration_id'] = form.instance.pk
message = _(u'Deine Anmeldung wurde erfolgreich gespeichert.')
messages.success(self.request, message)
return r
def post(self, request, *args, **kwargs):
if 'registration_id' in request.session:
del request.session['registration_id']
return super(RegistrationView, self).post(request, *args, **kwargs)
class RegistrationSuccessView(generic.DetailView):
model = Registration
def get_object(self, queryset=None):
try:
pk = self.request.session['registration_id']
obj = self.model.objects.get(pk=pk)
except KeyError, self.model.DoesNotExist:
obj = None
return obj