From 5bb2edc74955192010c763064136d458f1b645e9 Mon Sep 17 00:00:00 2001 From: Jens Kleineheismann Date: Tue, 20 Feb 2018 17:19:15 +0100 Subject: [PATCH] Moved most form field initial values from forms to settings. --- dav_events/apps.py | 1 + dav_events/config.py | 66 ++++++++ .../django.main.settings-dav_events.py | 144 ++++++++++++++++++ dav_events/forms/events.py | 134 +--------------- dav_events/forms/generic.py | 9 +- 5 files changed, 226 insertions(+), 128 deletions(-) diff --git a/dav_events/apps.py b/dav_events/apps.py index c983458..3361f25 100644 --- a/dav_events/apps.py +++ b/dav_events/apps.py @@ -16,6 +16,7 @@ DEFAULT_SETTINGS = ( DefaultSetting('group_publish_incremental', None), DefaultSetting('forms_development_init', False), DefaultSetting('matrix_config', ImproperlyConfigured), + DefaultSetting('form_initials', dict()), ) diff --git a/dav_events/config.py b/dav_events/config.py index 9712de1..51f83c8 100644 --- a/dav_events/config.py +++ b/dav_events/config.py @@ -1,8 +1,11 @@ import importlib +import logging import re from django.apps import AppConfig as _AppConfig from django.core.exceptions import ImproperlyConfigured +logger = logging.getLogger(__name__) + # Form and Model Field Config COMMON_CHAR_FIELD_LENGTH = 250 NUMBER_MAX_LENGTH = 12 @@ -18,6 +21,69 @@ MEALS_OTHER_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH ADDITIONAL_COSTS_MAX_LENGTH = COMMON_CHAR_FIELD_LENGTH +class FieldInitial(object): + _constraint_re = re.compile(r'^(?P[a-z_]+)(?P[=]+)(?P.*)$') + + def __init__(self, *args): + self._tuples = [] + + if len(args) == 1: + self._tuples = [(None, args[0])] + else: + constraint = None + for arg in args: + if constraint is None: + constraint = arg + else: + self._tuples.append((constraint, arg)) + constraint = None + + def get_value(self, session_data): + parameters = { + 'mode': session_data.get('mode', None), + 'sport': session_data.get('sport', None), + 'level': session_data.get('level', None), + 'country': session_data.get('country', None), + 'terrain': session_data.get('terrain', None), + 'overnight': str(bool(session_data.get('last_day', None))), + } + for tuple in self._tuples: + constraint, result = tuple + + if not constraint: + return result + + match = False + constraint_parts = constraint.split(',') + for sub_constraint in constraint_parts: + c = self._constraint_re.match(sub_constraint) + if c is not None: + c_field = c.group('field') + if c_field not in parameters: + logger.error('FieldInitial: Invalid field: \'%s\'', sub_constraint) + continue + c_op = c.group('op') + c_value = c.group('value') + if c_op == '==': + if parameters[c_field] == c_value: + match = True + continue + else: + match = False + break + else: + logger.error('FieldInitial: Invalid operator: \'%s\'', sub_constraint) + continue + else: + logger.error('FieldInitial: Invalid constraint: \'%s\'', constraint) + break + + if match: + return result + + return None + + class DefaultSetting(object): def __init__(self, name, value, key_name=None, validator=None): self.name = name diff --git a/dav_events/console_scripts/Resources/django.main.settings-dav_events.py b/dav_events/console_scripts/Resources/django.main.settings-dav_events.py index 997faec..ad95948 100644 --- a/dav_events/console_scripts/Resources/django.main.settings-dav_events.py +++ b/dav_events/console_scripts/Resources/django.main.settings-dav_events.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- from django.utils.translation import ugettext_lazy as _ +from dav_events.config import FieldInitial # E-Mails ENABLE_EMAIL_NOTIFICATIONS = False @@ -128,3 +129,146 @@ MATRIX_CONFIG = { 'max_participants': 4, }, } + +FORM_INITIALS = { + 'ModeForm': { + 'mode': FieldInitial('joint'), + 'sport': FieldInitial('W'), + 'level': FieldInitial('beginner'), + }, + 'LocationForm': { + 'country': FieldInitial( + 'sport==B', + 'FR', + 'sport==S,overnight==True', + 'AT', + 'sport==W,overnight==True', + 'AT', + '', + 'DE', + ), + 'terrain': FieldInitial( + 'sport==B', + 'alpine', + 'sport==K', + 'crag', + 'sport==S,overnight==True', + 'alpine', + 'sport==W,overnight==True', + 'alpine', + '', + 'submountains', + ), + }, + 'ApproachForm': { + 'transport': FieldInitial( + 'sport==M,country==DE,terrain==submountains', + 'public', + 'sport==W,country==DE,terrain==submountains', + 'public', + ), + 'meeting_point': FieldInitial( + 'sport==M,country==DE,terrain==submountains', + 'hbf', + 'sport==W,country==DE,terrain==submountains', + 'hbf', + ), + 'accommodation': FieldInitial('terrain==alpine', 'hut'), + 'meals': FieldInitial('NONE'), + }, + 'RequirementsForm': { + 'equipment': FieldInitial( + 'sport==B', + _(u'Steigeisen*, Pickel*, Klettergurt*, Steinschlaghelm*,' + u' Gletscherbrille, wasserfeste Kleidung, Gamaschen' + u' (* Ausrüstung kann ggf. von der Sektion geliehen werden)'), + 'sport==K', + _(u'Kletterschuhe, Hüftgurt*, Steinschlaghelm*' + u' (* Ausrüstung kann ggf. von der Sektion geliehen werden)'), + 'sport==M', + _(u'Funktionstüchtiges MTB (bitte vorher überprüfen), Fahrrad-Helm' + u' und Radhandschuhe sind zwingend erforderlich,' + u' Brille und Protektoren empfehlenswert.' + u' Die Sattelstütze muss sich tief versenken lassen.'), + 'sport==S', + _(u'Komplette Skitourenausrüstung inkl. Ski, Lawinen-Pieps*, Schaufel* und Sonde*' + u' (* Ausrüstung kann ggf. von der Sektion geliehen werden)'), + 'sport==W,terrain==alpine', + _(u'Feste, knöchelhohe Wanderschuhe, Regenschutz'), + 'sport==W', + _(u'Festes Schuhwerk, Regenschutz'), + ), + 'requirements': FieldInitial( + 'sport==B,level==beginner', + _(u'Kondition für ganztätige Aktivität im Freien' + u' mit Auf- und Abstiegen bis zu 1000 Hm.'), + 'sport==B', + _(u'Sicheres Vorsteigen am Fels im 4. Grad UIAA.' + u' Grundkentnisse Hochtouren, Spaltenbergung.' + u' Kondition für Auf- und Abstiege bis zu 1300 Hm.'), + 'sport==K,level==beginner', + _(u'Sicheres Klettern im 4. Grad UIAA.' + u' Beherrschen der Sicherungstechnik.'), + 'sport==K', + _(u'Sicheres Vorsteigen am Fels im 5. Grad UIAA.' + u' Beherrschen der Sicherungs- und Abseiltechnik.'), + 'sport==M,level==beginner', + _(u'Kondition für Radtouren bis 30 km und 500 Hm' + u' in ca. 3 Stunden.'), + 'sport==M', + _(u'Kondition für Radtouren bis 60 km und 1000 Hm' + u' in ca. 5 Stunden.' + u' Sicheres Beherrschen von Trails der Schwierigkeit S1.'), + 'sport==S,level==beginner', + _(u'Sicheres Skifahren und erste Erfahrungen abseits' + u' der gespurten Piste.'), + 'sport==S', + _(u'Mittelschwere, lange Skitouren bis 1500 Hm.' + u' Solide Aufstiegs- und Abfahrtstechnik.'), + 'sport==W,terrain==alpine', + _(u'Kondition für 20km und 600 Hm in ca. 7 Stunden Gehzeit.' + u' Trittsicherheit (mittelschwere Wege).'), + 'sport==W', + _(u'Gehzeit X-Y Stunden, ca. X km, ca. X Hm'), + ), + }, + 'RegistrationForm': { + 'deadline': FieldInitial('OTHER'), + 'registration_howto': FieldInitial( + 'sport==B', + _(u'Anmeldung mit Vor- und Nachname, E-Mail-Adresse, Telefonnummer (Mobil),' + u' Notfall-Kontakt, DAV-Mitgliedsnummer' + u' sowie Beschreibung der eigenen Bergerfahrung' + u' bei %(name)s (%(emailaddr)s).'), + 'sport==K,terrain==alpine', + _(u'Anmeldung mit Vor- und Nachname, E-Mail-Adresse, Telefonnummer (Mobil),' + u' Notfall-Kontakt, DAV-Mitgliedsnummer' + u' sowie Beschreibung der eigenen Fels- bzw. Bergerfahrung' + u' bei %(name)s (%(emailaddr)s).'), + 'sport==K', + _(u'Anmeldung mit Vor- und Nachname, E-Mail-Adresse, Telefonnummer (Mobil),' + u' DAV-Mitgliedsnummer' + u' sowie Beschreibung der eigenen Klettererfahrung' + u' bei %(name)s (%(emailaddr)s).'), + 'sport==M,terrain==alpine', + _(u'Anmeldung mit Vor- und Nachname, E-Mail-Adresse, Telefonnummer (Mobil),' + u' Notfall-Kontakt, DAV-Mitgliedsnummer' + u' sowie kurzer Beschreibung der eigenen MTB-Erfahrung' + u' bei %(name)s (%(emailaddr)s).'), + 'sport==M', + _(u'Anmeldung mit Vor- und Nachname, E-Mail-Adresse, Telefonnummer (Mobil),' + u' DAV-Mitgliedsnummer' + u' sowie kurzer Beschreibung der eigenen MTB-Erfahrung' + u' bei %(name)s (%(emailaddr)s).'), + 'sport==S', + _(u'Anmeldung mit Vor- und Nachname, E-Mail-Adresse, Telefonnummer (Mobil),' + u' Notfall-Kontakt, DAV-Mitgliedsnummer' + u' sowie Beschreibung der eigenen Skitouren- und Bergerfahrung' + u' bei %(name)s (%(emailaddr)s).'), + 'terrain==alpine', + _(u'Anmeldung mit Vor- und Nachname, E-Mail-Adresse, Telefonnummer (Mobil),' + u' Notfall-Kontakt und DAV-Mitgliedsnummer' + u' bei %(name)s (%(emailaddr)s).'), + ), + }, +} diff --git a/dav_events/forms/events.py b/dav_events/forms/events.py index cb35f5e..bfd4c56 100644 --- a/dav_events/forms/events.py +++ b/dav_events/forms/events.py @@ -83,17 +83,17 @@ class EventCreateForm(ChainedForm): ski_lift = session_data.get('ski_lift', False) terrain = session_data.get('terrain', None) country = session_data.get('country', None) - last_day = session_data.get('last_day', None) + overnight = bool(session_data.get('last_day', None)) if sport == 'S' and ski_lift: matrix_key = 'K' - elif sport == 'W' and not last_day: + elif sport == 'W' and not overnight: matrix_key = '0' elif sport == 'W' and terrain != 'alpine': matrix_key = 'A' elif sport == 'W': matrix_key = 'B' - elif terrain != 'alpine' and not last_day: + elif terrain != 'alpine' and not overnight: matrix_key = 'C' elif terrain != 'alpine': matrix_key = 'D' @@ -118,12 +118,10 @@ class ModeForm(EventCreateForm): _next_form_name = 'LocationForm' mode = forms.ChoiceField(choices=choices.MODE_CHOICES, - initial='joint', label=_(u'Veranstaltungsart'), widget=forms.RadioSelect()) sport = forms.ChoiceField(choices=choices.SPORT_CHOICES, - initial='W', label=_(u'Spielart'), widget=forms.RadioSelect()) @@ -133,7 +131,6 @@ class ModeForm(EventCreateForm): ) level = forms.ChoiceField(choices=choices.LEVEL_CHOICES, - initial='beginner', label=_(u'Schwierigkeitsnivau'), widget=forms.RadioSelect()) @@ -258,11 +255,9 @@ class LocationForm(EventCreateForm): _next_form_name = 'ApproachForm' country = LazyTypedChoiceField(choices=choices.COUNTRY_CHOICES, - initial='DE', label=_(u'Land')) terrain = forms.ChoiceField(choices=choices.TERRAIN_CHOICES, - initial='submountains', label=_(u'Gelände'), help_text=_(u'Relevant für die Vorauswahl weiterer Felder.'), ) @@ -286,28 +281,18 @@ class LocationForm(EventCreateForm): sport = session_data.get('sport', None) last_day = session_data.get('last_day', None) if sport == 'B': - self.fields['terrain'].initial = 'alpine' - self.fields['country'].initial = 'FR' self.fields['location'].widget.attrs['placeholder'] = u'z.B. Chamonix, Mont-Blanc-Gruppe' elif sport == 'K': - self.fields['terrain'].initial = 'crag' self.fields['location'].widget.attrs['placeholder'] = u'z.B. Battert, Baden-Baden' elif sport == 'M': - self.fields['terrain'].initial = 'submountains' self.fields['location'].widget.attrs['placeholder'] = u'z.B. Pfälzerwald' elif sport == 'S' and last_day: - self.fields['terrain'].initial = 'alpine' - self.fields['country'].initial = 'AT' self.fields['location'].widget.attrs['placeholder'] = u'z.B. Obergurgl, Ötztaler Alpen' elif sport == 'S': - self.fields['terrain'].initial = 'submountains' self.fields['location'].widget.attrs['placeholder'] = u'z.B. Todtnau, Schwarzwald' elif sport == 'W' and last_day: - self.fields['terrain'].initial = 'alpine' - self.fields['country'].initial = 'AT' self.fields['location'].widget.attrs['placeholder'] = u'z.B. Ötztaler Alpen' elif sport == 'W': - self.fields['terrain'].initial = 'submountains' self.fields['location'].widget.attrs['placeholder'] = u'z.B. Maikammer, Pfalz' @@ -382,7 +367,6 @@ class ApproachForm(EventCreateForm): ) meals = forms.ChoiceField(choices=choices.MEALS_CHOICES, - initial='NONE', label=_(u'Verpflegung'), ) meals_other = forms.CharField(required=False, @@ -394,9 +378,6 @@ class ApproachForm(EventCreateForm): super(ApproachForm, self)._proceed_session_data(session_data) last_day = session_data.get('last_day', None) - sport = session_data.get('sport', None) - country = session_data.get('country', None) - terrain = session_data.get('terrain', None) self.fields['transport_other'].widget.attrs['placeholder'] = _(u'Nebenstehendes Feld beachten') self.fields['meeting_point_other'].widget.attrs['placeholder'] = _(u'Nebenstehendes Feld beachten') @@ -404,14 +385,6 @@ class ApproachForm(EventCreateForm): self.fields['accommodation_other'].widget.attrs['placeholder'] = _(u'Nebenstehendes Feld beachten') self.fields['meals_other'].widget.attrs['placeholder'] = _(u'Nebenstehendes Feld beachten') - if terrain == 'alpine': - self.fields['accommodation'].initial = 'hut' - - if sport in ('M', 'W'): - if country == 'DE' and terrain == 'submountains': - self.fields['transport'].initial = 'public' - self.fields['meeting_point'].initial = 'hbf' - if not last_day: self.fields['basecamp'].widget = forms.HiddenInput() self.fields['accommodation'].widget = forms.HiddenInput() @@ -476,70 +449,6 @@ class RequirementsForm(EventCreateForm): }, bootstrap_version=3)) - def _proceed_session_data(self, session_data): - super(RequirementsForm, self)._proceed_session_data(session_data) - - sport = session_data.get('sport', None) - level = session_data.get('level', None) - terrain = session_data.get('terrain', None) - - if sport == 'B': - self.fields['equipment'].initial = u'%s (%s)' % ( - _(u'Steigeisen*, Pickel*, Klettergurt*, Steinschlaghelm*,' - u' Gletscherbrille, wasserfeste Kleidung, Gamaschen'), - _(u'* Ausrüstung kann ggf. von der Sektion geliehen werden') - ) - - if level == 'beginner': - self.fields['requirements'].initial = _(u'Kondition für ganztätige Aktivität im Freien' - u' mit Auf- und Abstiegen bis zu 1000 Hm.') - else: - self.fields['requirements'].initial = _(u'Sicheres Vorsteigen am Fels im 4. Grad UIAA.' - u' Grundkentnisse Hochtouren, Spaltenbergung.' - u' Kondition für Auf- und Abstiege bis zu 1300 Hm.') - elif sport == 'K': - self.fields['equipment'].initial = u'%s (%s)' % ( - _(u'Kletterschuhe, Hüftgurt*, Steinschlaghelm*'), - _(u'* Ausrüstung kann ggf. von der Sektion geliehen werden') - ) - if level == 'beginner': - self.fields['requirements'].initial = _(u'Sicheres Klettern im 4. Grad UIAA.' - u' Beherrschen der Sicherungstechnik.') - else: - self.fields['requirements'].initial = _(u'Sicheres Vorsteigen am Fels im 5. Grad UIAA.' - u' Beherrschen der Sicherungs- und Abseiltechnik.') - elif sport == 'M': - self.fields['equipment'].initial = _(u'Funktionstüchtiges MTB (bitte vorher überprüfen), Fahrrad-Helm' - u' und Radhandschuhe sind zwingend erforderlich,' - u' Brille und Protektoren empfehlenswert.' - u' Die Sattelstütze muss sich tief versenken lassen.') - if level == 'beginner': - self.fields['requirements'].initial = _(u'Kondition für Radtouren bis 30 km und 500 Hm' - u' in ca. 3 Stunden.') - else: - self.fields['requirements'].initial = _(u'Kondition für Radtouren bis 60 km und 1000 Hm' - u' in ca. 5 Stunden.' - u' Sicheres Beherrschen von Trails der Schwierigkeit S1.') - elif sport == 'S': - self.fields['equipment'].initial = u'%s (%s)' % ( - _(u'Komplette Skitourenausrüstung inkl. Ski, Lawinen-Pieps*, Schaufel* und Sonde*'), - _(u'* Ausrüstung kann ggf. von der Sektion geliehen werden') - ) - if level == 'beginner': - self.fields['requirements'].initial = _(u'Sicheres Skifahren und erste Erfahrungen abseits' - u' der gespurten Piste.') - else: - self.fields['requirements'].initial = _(u'Mittelschwere, lange Skitouren bis 1500 Hm.' - u' Solide Aufstiegs- und Abfahrtstechnik.') - elif sport == 'W': - if terrain == 'alpine': - self.fields['equipment'].initial = _(u'Feste, knöchelhohe Wanderschuhe, Regenschutz') - self.fields['requirements'].initial = _(u'Kondition für 20km und 600 Hm in ca. 7 Stunden Gehzeit.' - u' Trittsicherheit (mittelschwere Wege).') - else: - self.fields['equipment'].initial = _(u'Festes Schuhwerk, Regenschutz') - self.fields['requirements'].initial = _(u'Gehzeit X-Y Stunden, ca. X km, ca. X Hm') - class DescriptionForm(EventCreateForm): _form_title = _(u'Titel / Beschreibung') @@ -664,7 +573,6 @@ class RegistrationForm(EventCreateForm): label=_(u'Max. Teilnehmer')) deadline = forms.ChoiceField(choices=choices.DEADLINE_CHOICES, - initial='OTHER', label=_(u'Anmeldeschluss'), widget=forms.RadioSelect()) @@ -697,8 +605,6 @@ class RegistrationForm(EventCreateForm): def _proceed_session_data(self, session_data): super(RegistrationForm, self)._proceed_session_data(session_data) - sport = session_data.get('sport', None) - terrain = session_data.get('terrain', None) first_day = session_data.get('first_day', None) trainer_fullname = u'%s %s' % (session_data.get('trainer_firstname'), session_data.get('trainer_familyname')) trainer_email = session_data.get('trainer_email') @@ -738,36 +644,10 @@ class RegistrationForm(EventCreateForm): new_choices.append((key, desc)) self.fields['deadline'].choices = new_choices - registration_howto = _(u'Anmeldung mit Vor- und Nachname, E-Mail-Adresse, Telefonnummer (Mobil)' - u'%(additional)s bei %(name)s (%(emailaddr)s).') - additional = u'' - if sport == 'B': - additional = u'%s %s' % (_(u', Notfall-Kontakt, DAV-Mitgliedsnummer'), - _(u'sowie Beschreibung der eigenen Bergerfahrung')) - elif sport == 'K' and terrain == 'alpine': - additional = u'%s %s' % (_(u', Notfall-Kontakt, DAV-Mitgliedsnummer'), - _(u'sowie Beschreibung der eigenen Fels- bzw. Bergerfahrung')) - elif sport == 'K': - additional = u'%s %s' % (_(u', DAV-Mitgliedsnummer'), - _(u'sowie Beschreibung der eigenen Klettererfahrung')) - elif sport == 'M' and terrain == 'alpine': - additional = u'%s %s' % (_(u', Notfall-Kontakt, DAV-Mitgliedsnummer'), - _(u'sowie kurzer Beschreibung der eigenen MTB-Erfahrung')) - elif sport == 'M': - additional = u'%s %s' % (_(u', DAV-Mitgliedsnummer'), - _(u'sowie kurzer Beschreibung der eigenen MTB-Erfahrung')) - elif sport == 'S': - additional = u'%s %s' % (_(u', Notfall-Kontakt, DAV-Mitgliedsnummer'), - _(u'sowie Beschreibung der eigenen Skitouren- und Bergerfahrung')) - elif terrain == 'alpine': - additional = _(u', Notfall-Kontakt und DAV-Mitgliedsnummer') - else: - registration_howto = None - - if registration_howto: - self.fields['registration_howto'].initial = registration_howto % {'name': trainer_fullname, - 'emailaddr': trainer_email, - 'additional': additional} + if self.fields['registration_howto'].initial: + initial = self.fields['registration_howto'].initial % {'name': trainer_fullname, + 'emailaddr': trainer_email} + self.fields['registration_howto'].initial = initial else: self.fields['registration_howto'].widget = forms.HiddenInput() diff --git a/dav_events/forms/generic.py b/dav_events/forms/generic.py index ca7440f..ed1f6fa 100644 --- a/dav_events/forms/generic.py +++ b/dav_events/forms/generic.py @@ -1,10 +1,12 @@ import logging from django import forms +from django.apps import apps from django.core.exceptions import ImproperlyConfigured from .. import converters logger = logging.getLogger(__name__) +app_config = apps.get_containing_app_config(__package__) class ChainedForm(forms.Form): @@ -40,7 +42,12 @@ class ChainedForm(forms.Form): self._session_data[k] = self._deserialize_value(session_data[k]) def _proceed_session_data(self, session_data): - pass + form_initials = app_config.settings.form_initials.get(self.__class__.__name__, dict()) + for fieldname in self.fields: + if fieldname in form_initials: + value = form_initials[fieldname].get_value(session_data) + if value is not None: + self.fields[fieldname].initial = value def _save_session_data(self): if self._request is not None and hasattr(self._request, 'session'):