#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (C) 2010 Étienne Loks # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # See the file COPYING for details. """ Forms definition """ import datetime from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ from django.template import Context, RequestContext from django.shortcuts import render_to_response from django.forms.formsets import formset_factory from django import forms from formwizard.forms import NamedUrlSessionFormWizard import models import widgets from ishtar import settings from django.utils.functional import lazy reverse_lazy = lazy(reverse, unicode) class FinalForm(forms.Form): final = True form_label = _("Confirm") class Wizard(NamedUrlSessionFormWizard): def get_template(self, request, storage): templates = ['default_wizard.html'] current_step = storage.get_current_step() or '0' if current_step == self.get_last_step(request, storage): templates = ['confirm_wizard.html'] + templates return templates def get_template_context(self, request, storage, form=None): """ Add previous and current steps to manage the wizard path """ context = super(Wizard, self).get_template_context(request, storage, form) step = self.get_first_step(request, storage) current_step = storage.get_current_step() or '0' context.update({'current_step':self.form_list[current_step]}) if step == current_step: return context previous_steps = [] while step: if step == current_step: break previous_steps.append(self.form_list[step]) step = self.get_next_step(request, storage, step) context.update({'previous_steps':previous_steps}) # not last step: validation if step != self.get_last_step(request, storage): return context final_form_list = [] for form_key in self.get_form_list(request, storage).keys(): form_obj = self.get_form(request, storage, step=form_key, data=storage.get_step_data(form_key), files=storage.get_step_files(form_key)) form_obj.is_valid() final_form_list.append(form_obj) context.update({'datas':self.get_formated_datas(final_form_list)}) return context def get_formated_datas(self, forms): """ Get the data to present in the last page """ datas = [] for form in forms: base_form = hasattr(form, 'forms') and form.forms[0] or form associated_models = hasattr(base_form, 'associated_models') and \ base_form.associated_models or {} if not hasattr(form, 'cleaned_data'): continue cleaned_datas = type(form.cleaned_data) == list and \ form.cleaned_data \ or [form.cleaned_data] for cleaned_data in cleaned_datas: for key in cleaned_data: lbl = key if hasattr(base_form, 'fields') and key in base_form.fields: lbl = base_form.fields[key].label value = cleaned_data[key] if key in associated_models: value = unicode(associated_models[key].objects.get( pk=value)) datas.append((lbl, value)) return datas def done(self, request, storage, form_list, **kwargs): """ Save to the model """ dct, m2m = {}, [] for form in form_list: base_form = hasattr(form, 'forms') and form.forms[0] or form associated_models = hasattr(base_form, 'associated_models') and \ base_form.associated_models or {} if type(form.cleaned_data) == dict: for key in form.cleaned_data: value = form.cleaned_data[key] if key in associated_models: value = associated_models[key].objects.get(pk=value) dct[key] = value elif type(form.cleaned_data) == list: for item in form.cleaned_data: for key in item: if key not in associated_models: # datas not managed continue value = item[key] value = associated_models[key].objects.get(pk=value) m2m.append((key, value)) dct['history_modifier'] = request.user fle = models.File(**dct) fle.save() for key, value in m2m: getattr(fle, key+'s').add(value) return render_to_response('wizard_done.html', {}, context_instance=RequestContext(request)) def get_form(self, request, storage, step=None, data=None, files=None): """ Manage formset """ if data: data = data.copy() if not step: step = self.determine_step(request, storage) form = self.get_form_list(request, storage)[step] if hasattr(form, 'management_form'): # get a form key base_key = form.form.base_fields.keys()[0] total_field = len([key for key in data.keys() if base_key in key.split('-') and data[key]]) data[step + u'-INITIAL_FORMS'] = unicode(total_field) data[step + u'-TOTAL_FORMS'] = unicode(total_field + 1) form = super(Wizard, self).get_form(request, storage, step, data, files) return form def render_next_step(self, request, storage, form, **kwargs): """ Manage the modify button in formset: next_step = current_step """ if request.POST.has_key('formset_modify') and \ request.POST['formset_modify']: return self.render(request, storage, form, **kwargs) return super(Wizard, self).render_next_step(request, storage, form, **kwargs) class FileWizard(Wizard): pass class FileForm1(forms.Form): form_label = _("General") associated_models = {'in_charge':models.Person, 'file_type':models.FileType} in_charge = forms.IntegerField(label=_("Person in charge"), widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'), associated_model=models.Person), validators=[models.Person.valid_id]) year = forms.IntegerField(label=_("Year"), initial=lambda:datetime.datetime.now().year) internal_reference = forms.CharField(label=_(u"Internal reference"), max_length=60) creation_date = forms.DateField(label=_(u"Creation date"), initial=datetime.datetime.now) file_type = forms.ChoiceField(label=_("File type"), choices=models.FileType.get_types()) comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea, required=False) class FileForm2(forms.Form): form_label = _("Address") total_surface = forms.IntegerField(label=_("Total surface")) address = forms.CharField(label=_(u"Address"), widget=forms.Textarea) class TownForm(forms.Form): form_label = _("Towns") associated_models = {'town':models.Town} # !FIXME hard_link, reverse_lazy doen't seem to work with formsets town = forms.IntegerField(label=_(u"Town"), widget=widgets.JQueryAutoComplete("/" + settings.URL_PATH + \ 'autocomplete-town', associated_model=models.Town), validators=[models.Town.valid_id], required=False) TownFormSet = formset_factory(TownForm) TownFormSet.form_label = _("Towns") class FileForm3(forms.Form): form_label = _("Preventive informations") associated_models = {'general_contractor':models.Organization, 'saisine_type':models.SaisineType} general_contractor = forms.IntegerField(label=_(u"General contractor"), widget=widgets.JQueryAutoComplete( reverse_lazy('autocomplete-organization'), associated_model=models.Organization), validators=[models.Organization.valid_id]) total_developed_surface = forms.IntegerField( label=_("Total developed surface")) if settings.COUNTRY == 'fr': saisine_type = forms.ChoiceField(label=_("Saisine type"), choices=models.SaisineType.get_types()) reception_date = forms.DateField(label=_(u"Reception date")) def is_preventive(self, request, storage): if storage.prefix not in request.session or \ 'step_data' not in request.session[storage.prefix] or \ '0' not in request.session[storage.prefix]['step_data'] or\ '0-file_type' not in request.session[storage.prefix]['step_data']['0']: return False try: file_type = int(request.session[storage.prefix]['step_data']['0']\ ['0-file_type']) return models.FileType.is_preventive(file_type) except ValueError: return False file_creation_wizard = FileWizard([FileForm1, FileForm2, TownFormSet, FileForm3, FinalForm], url_name='file_creation', condition_list={'3':is_preventive})