diff --git a/dav_events/forms/__init__.py b/dav_events/forms/__init__.py new file mode 100644 index 0000000..eabec01 --- /dev/null +++ b/dav_events/forms/__init__.py @@ -0,0 +1,3 @@ +from . import generic +from . import auth +from . import events diff --git a/dav_events/forms/auth.py b/dav_events/forms/auth.py new file mode 100644 index 0000000..0f7a66c --- /dev/null +++ b/dav_events/forms/auth.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +import logging +from django import forms +from django.contrib.auth import forms as auth_forms, password_validation +from django.utils.translation import ugettext, ugettext_lazy as _ + +logger = logging.getLogger(__name__) + + +class LoginForm(auth_forms.AuthenticationForm): + username = auth_forms.UsernameField( + max_length=254, + label=_(u'E-Mail-Adresse'), + widget=forms.TextInput(attrs={'autofocus': True}), + ) + + error_messages = { + 'invalid_login': _(u'Benutzername oder Passwort falsch.'), + 'inactive': _("This account is inactive."), + } + + def clean_username(self): + username = self.cleaned_data.get('username') + return username.lower() + + +class SetPasswordForm(forms.Form): + new_password = forms.CharField(max_length=12, + label=_(u'Neues Passwort'), + widget=forms.PasswordInput) + new_password_repeat = forms.CharField(max_length=12, + label=_(u'Neues Passwort wiederholen'), + widget=forms.PasswordInput) + send_password_mail = forms.BooleanField(required=False, + label=_(u'Neues Passwort per E-Mail zusenden'), + ) + + def __init__(self, user, *args, **kwargs): + self.user = user + super(SetPasswordForm, self).__init__(*args, **kwargs) + + def clean_new_password(self): + password = self.cleaned_data.get('new_password') + password_validation.validate_password(password, self.user) + return password + + def clean_new_password_repeat(self): + password1 = self.cleaned_data.get('new_password') + password2 = self.cleaned_data.get('new_password_repeat') + if password1 and password2: + if password1 != password2: + raise forms.ValidationError( + ugettext(u'Passwörter stimmen nicht überein'), + code='password_mismatch', + ) + return password2 + + def save(self, commit=True): + new_password = self.cleaned_data.get('new_password') + self.user.set_password(new_password) + if commit: + self.user.save() + return self.user diff --git a/dav_events/forms.py b/dav_events/forms/events.py similarity index 87% rename from dav_events/forms.py rename to dav_events/forms/events.py index f0027c7..cdd5c15 100644 --- a/dav_events/forms.py +++ b/dav_events/forms/events.py @@ -4,185 +4,19 @@ import datetime import logging from babel.dates import format_date from django import forms -from django.contrib.auth import forms as auth_forms, password_validation -from django.core.exceptions import ImproperlyConfigured from django.utils.translation import get_language, ugettext, ugettext_lazy as _ from django_countries.fields import LazyTypedChoiceField from datetimewidget.widgets import DateWidget, TimeWidget, DateTimeWidget -from . import choices -from . import config -from . import converters -from . import models +from .. import choices +from .. import config +from .. import models +from .generic import ChainedForm logger = logging.getLogger(__name__) DEVELOPMENT_INIT_FORMS = True -class LoginForm(auth_forms.AuthenticationForm): - username = auth_forms.UsernameField( - max_length=254, - label=_(u'E-Mail-Adresse'), - widget=forms.TextInput(attrs={'autofocus': True}), - ) - - error_messages = { - 'invalid_login': _(u'Benutzername oder Passwort falsch.'), - 'inactive': _("This account is inactive."), - } - - def clean_username(self): - username = self.cleaned_data.get('username') - return username.lower() - - -class SetPasswordForm(forms.Form): - new_password = forms.CharField(max_length=12, - label=_(u'Neues Passwort'), - widget=forms.PasswordInput) - new_password_repeat = forms.CharField(max_length=12, - label=_(u'Neues Passwort wiederholen'), - widget=forms.PasswordInput) - send_password_mail = forms.BooleanField(required=False, - label=_(u'Neues Passwort per E-Mail zusenden'), - ) - - def __init__(self, user, *args, **kwargs): - self.user = user - super(SetPasswordForm, self).__init__(*args, **kwargs) - - def clean_new_password(self): - password = self.cleaned_data.get('new_password') - password_validation.validate_password(password, self.user) - return password - - def clean_new_password_repeat(self): - password1 = self.cleaned_data.get('new_password') - password2 = self.cleaned_data.get('new_password_repeat') - if password1 and password2: - if password1 != password2: - raise forms.ValidationError( - ugettext(u'Passwörter stimmen nicht überein'), - code='password_mismatch', - ) - return password2 - - def save(self, commit=True): - new_password = self.cleaned_data.get('new_password') - self.user.set_password(new_password) - if commit: - self.user.save() - return self.user - - -class ChainedForm(forms.Form): - _initial_form_name = None - _next_form_name = None - - def __init__(self, *args, **kwargs): - self._session_data = dict() - self._request = kwargs.pop('request', None) - self._load_session_data() - - super(ChainedForm, self).__init__(*args, **kwargs) - - self._proceed_session_data(self._session_data) - - def _serialize_value(self, value): - return converters.Iso8601Serializer.serialize(value, ignore_unsupported_input=True) - - def _deserialize_value(self, value): - return converters.Iso8601Serializer.deserialize(value, ignore_unsupported_input=True) - - def _load_session_data(self): - if self._request is not None and hasattr(self._request, 'session'): - session_var_name = '{}_chained_form_session_data'.format(self._request.resolver_match.url_name) - session_data = self._request.session.get(session_var_name, dict()) - for k in session_data: - self._session_data[k] = self._deserialize_value(session_data[k]) - - def _save_session_data(self): - if self._request is not None and hasattr(self._request, 'session'): - session_var_name = '{}_chained_form_session_data'.format(self._request.resolver_match.url_name) - session_data = dict() - for k in self._session_data: - session_data[k] = self._serialize_value(self._session_data[k]) - self._request.session[session_var_name] = session_data - - def _proceed_session_data(self, session_data): - pass - - def _get_model(self): - if not hasattr(self, '_model'): - raise ImproperlyConfigured('{cls} is missing a Model.' - ' Define {cls}._model'.format(cls=self.__class__.__name__)) - return self._model - - def _get_object(self, model_kwargs): - return self._get_model()(**model_kwargs) - - @property - def form_name(self): - return self.__class__.__name__ - - @property - def form_title(self): - return self.__class__.get_form_title() - - @property - def initial_form_name(self): - return self.__class__.get_initial_form_name() - - @property - def next_form_name(self): - return self.__class__.get_next_form_name() - - @classmethod - def get_form_name(cls): - return cls.__name__ - - @classmethod - def get_form_title(cls): - if hasattr(cls, '_form_title'): - return cls._form_title - n = cls.get_form_name() - if n.endswith('Form'): - n = n[:-len('Form')] - return n - - @classmethod - def get_initial_form_name(cls): - return cls._initial_form_name or cls.__name__ - - @classmethod - def get_next_form_name(cls): - return cls._next_form_name - - def clean(self): - cleaned_data = super(ChainedForm, self).clean() - self._session_data.update(cleaned_data) - self._save_session_data() - return cleaned_data - - def save(self): - object_kwargs = dict() - data = self._session_data - if 'deadline' in data: - buf = data['deadline'] - if isinstance(buf, basestring): - deadline_choice = buf.lower() - deadline_field = 'deadline_{}'.format(deadline_choice) - if deadline_field in data: - data['deadline'] = data[deadline_field] - - model = self._get_model() - for field in data: - if hasattr(model, field): - object_kwargs[field] = data[field] - - return self._get_object(object_kwargs) - - class EventCreateForm(ChainedForm): _model = models.Event _initial_form_name = 'ModeForm' @@ -921,4 +755,4 @@ class ChargesForm(EventCreateForm): class SummaryForm(EventCreateForm): - _form_title = _(u'Zusammenfassung') \ No newline at end of file + _form_title = _(u'Zusammenfassung') diff --git a/dav_events/forms/generic.py b/dav_events/forms/generic.py new file mode 100644 index 0000000..caf5d2d --- /dev/null +++ b/dav_events/forms/generic.py @@ -0,0 +1,116 @@ +import logging +from django import forms +from django.core.exceptions import ImproperlyConfigured + +from .. import converters + +logger = logging.getLogger(__name__) + + +class ChainedForm(forms.Form): + _form_title = None + _initial_form_name = None + _next_form_name = None + + def __init__(self, *args, **kwargs): + self._session_data = dict() + self._request = kwargs.pop('request', None) + self._load_session_data() + + super(ChainedForm, self).__init__(*args, **kwargs) + + self._proceed_session_data(self._session_data) + + def _serialize_value(self, value): + return converters.Iso8601Serializer.serialize(value, ignore_unsupported_input=True) + + def _deserialize_value(self, value): + return converters.Iso8601Serializer.deserialize(value, ignore_unsupported_input=True) + + def _load_session_data(self): + if self._request is not None and hasattr(self._request, 'session'): + session_var_name = '{}_chained_form_session_data'.format(self._request.resolver_match.url_name) + session_data = self._request.session.get(session_var_name, dict()) + for k in session_data: + self._session_data[k] = self._deserialize_value(session_data[k]) + + def _save_session_data(self): + if self._request is not None and hasattr(self._request, 'session'): + session_var_name = '{}_chained_form_session_data'.format(self._request.resolver_match.url_name) + session_data = dict() + for k in self._session_data: + session_data[k] = self._serialize_value(self._session_data[k]) + self._request.session[session_var_name] = session_data + + def _proceed_session_data(self, session_data): + pass + + def _get_model(self): + if not hasattr(self, '_model'): + raise ImproperlyConfigured('{cls} is missing a Model.' + ' Define {cls}._model'.format(cls=self.__class__.__name__)) + return self._model + + def _get_object(self, model_kwargs): + return self._get_model()(**model_kwargs) + + @property + def form_name(self): + return self.__class__.__name__ + + @property + def form_title(self): + return self.__class__.get_form_title() + + @property + def initial_form_name(self): + return self.__class__.get_initial_form_name() + + @property + def next_form_name(self): + return self.__class__.get_next_form_name() + + @classmethod + def get_form_name(cls): + return cls.__name__ + + @classmethod + def get_form_title(cls): + if cls._form_title is not None: + return cls._form_title + n = cls.get_form_name() + if n.endswith('Form'): + n = n[:-len('Form')] + return n + + @classmethod + def get_initial_form_name(cls): + return cls._initial_form_name or cls.__name__ + + @classmethod + def get_next_form_name(cls): + return cls._next_form_name + + def clean(self): + cleaned_data = super(ChainedForm, self).clean() + self._session_data.update(cleaned_data) + self._save_session_data() + return cleaned_data + + def save(self): + object_kwargs = dict() + data = self._session_data + if 'deadline' in data: + buf = data['deadline'] + if isinstance(buf, basestring): + deadline_choice = buf.lower() + deadline_field = 'deadline_{}'.format(deadline_choice) + if deadline_field in data: + data['deadline'] = data[deadline_field] + + model = self._get_model() + for field in data: + if hasattr(model, field): + object_kwargs[field] = data[field] + + return self._get_object(object_kwargs) diff --git a/dav_events/views.py b/dav_events/views.py index fef9263..e6871c4 100644 --- a/dav_events/views.py +++ b/dav_events/views.py @@ -26,7 +26,7 @@ class ImprintView(generic.TemplateView): class LoginView(auth_views.LoginView): - form_class = forms.LoginForm + form_class = forms.auth.LoginForm next_page = reverse_lazy('dav_events:event_list') template_name = 'dav_events/auth/login_form.html' @@ -40,7 +40,7 @@ class LogoutView(auth_views.LogoutView): class SetPasswordView(auth_views.PasswordChangeView): - form_class = forms.SetPasswordForm + form_class = forms.auth.SetPasswordForm template_name = 'dav_events/auth/set_password_form.html' success_url = reverse_lazy('dav_events:event_list') @@ -137,7 +137,7 @@ class EventAcceptView(EventDetailView): class EventCreateView(generic.FormView): - form_class = forms.EventCreateForm + form_class = forms.events.EventCreateForm template_dir = os.path.join('dav_events', 'event_create') default_template_name = 'default.html' abort_url = reverse_lazy('dav_events:home') @@ -153,16 +153,16 @@ class EventCreateView(generic.FormView): def get_form_class(self, form_name=None): if form_name is not None: - form_class = getattr(forms, form_name) + form_class = getattr(forms.events, form_name) elif 'dav_events_event_create_next_form_name' in self.request.session: form_name = self.request.session['dav_events_event_create_next_form_name'] - form_class = getattr(forms, form_name) - if not issubclass(form_class, forms.ChainedForm): + form_class = getattr(forms.events, form_name) + if not issubclass(form_class, self.form_class): raise SuspiciousOperation('Invalid next form: {}'.format(form_name)) else: base_form_class = self.form_class initial_form_name = base_form_class.get_initial_form_name() - form_class = getattr(forms, initial_form_name) + form_class = getattr(forms.events, initial_form_name) return form_class