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)