summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@peacefrogs.net>2012-10-10 01:05:40 +0200
committerÉtienne Loks <etienne.loks@peacefrogs.net>2012-10-10 01:05:40 +0200
commit615457617e65019e0ce39b585f4eeb41b17ba61a (patch)
tree0057598919dfeec52bae4416274e548025dccd11
parent1b173c7353631e40b0f40d5cf7d60ad0b664aa9d (diff)
downloadIshtar-615457617e65019e0ce39b585f4eeb41b17ba61a.tar.bz2
Ishtar-615457617e65019e0ce39b585f4eeb41b17ba61a.zip
Django 1.4 migration - Begining work on FormWizard migration: person creation
-rw-r--r--ishtar/ishtar_base/forms.py597
-rw-r--r--ishtar/ishtar_base/forms_common.py25
-rw-r--r--ishtar/ishtar_base/forms_main.py8
-rw-r--r--ishtar/ishtar_base/management/commands/generate_rights.py12
-rw-r--r--ishtar/ishtar_base/urls.py159
-rw-r--r--ishtar/ishtar_base/views.py627
-rw-r--r--ishtar/templates/ishtar/wizard/confirm_wizard.html (renamed from ishtar/templates/confirm_wizard.html)5
-rw-r--r--ishtar/templates/ishtar/wizard/default_wizard.html (renamed from ishtar/templates/default_wizard.html)12
-rw-r--r--ishtar/urls.py2
9 files changed, 750 insertions, 697 deletions
diff --git a/ishtar/ishtar_base/forms.py b/ishtar/ishtar_base/forms.py
index d947b43ae..3d6f3f503 100644
--- a/ishtar/ishtar_base/forms.py
+++ b/ishtar/ishtar_base/forms.py
@@ -40,7 +40,18 @@ from django.forms.formsets import formset_factory, BaseFormSet, \
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
-from formwizard.forms import NamedUrlSessionFormWizard
+# from formwizard.forms import NamedUrlSessionFormWizard
+
+class NamedUrlSessionFormWizard(forms.Form):
+ def __init__(self, form_list, condition_list={}, url_name=''):
+ self.form_list = dict(form_list)
+ self.condition_list = condition_list
+ self.url_name = url_name
+ super(NamedUrlSessionFormWizard, self).__init__(self)
+
+
+ def rindex(self, idx):
+ return self.url_name.rindex(idx)
import models
import widgets
@@ -90,6 +101,7 @@ class FormSet(BaseFormSet):
form.fields[DELETION_FIELD_NAME].label = ''
form.fields[DELETION_FIELD_NAME].widget = widgets.DeleteWidget()
+'''
class SearchWizard(NamedUrlSessionFormWizard):
model = None
@@ -103,587 +115,6 @@ class SearchWizard(NamedUrlSessionFormWizard):
templates = ['search.html']
return templates
-class Wizard(NamedUrlSessionFormWizard):
- model = None
- modification = None # True when the wizard modify an item
-
- @staticmethod
- def _check_right(step, condition=True):
- '''Return a method to check the right for a specific step'''
- def check_right(self, request, storage):
- cond = condition
- if callable(condition):
- cond = condition(self, request, storage)
- if not cond:
- return False
- person_type = request.user.ishtaruser.person.person_type
- if person_type.txt_idx == 'administrator':
- return True
- if person_type.rights.filter(url_name=step).count():
- return True
- return check_right
-
- def __init__(self, *args, **kwargs):
- """Check right for each step of the wizard"""
- super(Wizard, self).__init__(*args, **kwargs)
- for form_key in self.form_list.keys()[:-1]:
- condition = True
- if form_key in self.condition_list:
- condition = self.condition_list.get(form_key, True)
- cond = self._check_right(form_key, condition)
- self.condition_list[form_key] = cond
-
- def get_wizard_name(self):
- """As the class name can interfere when reused, use the url_name"""
- return self.url_name
-
- def get_template(self, request, storage):
- templates = ['default_wizard.html']
- current_step = storage.get_current_step() or self.get_first_step(
- request, storage)
- 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, next 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 self.get_first_step(
- request, storage)
- context.update({'current_step':self.form_list[current_step]})
- if step == current_step:
- return context
- previous_steps, next_steps, previous_step_counter = [], [], 0
- while step:
- if step == current_step:
- break
- previous_steps.append(self.form_list[step])
- step = self.get_next_step(request, storage, step)
- previous_step_counter += 1
- context.update({'previous_steps':previous_steps,
- 'previous_step_counter':previous_step_counter})
- # if modification: show the next steps
- if self.modification:
- next_step = step
- while next_step:
- # check if the form is initialized otherwise initialize it
- if not storage.get_step_data(next_step):
- values = self.get_form_initial(request, storage, next_step)
- prefixed_values = {}
- if not isinstance(values, list):
- for key in values:
- form_key = next_step + '-' + key
- prefixed_values[form_key] = values[key]
- else:
- for formset_idx, v in enumerate(values):
- prefix = u"-%d-" % formset_idx
- for key in v:
- form_key = next_step + prefix + key
- prefixed_values[form_key] = v[key]
- storage.set_step_data(next_step, prefixed_values)
- if step != next_step: # if not current step
- next_steps.append(self.form_list[next_step])
- next_step = self.get_next_step(request, storage, next_step)
- context.update({'next_steps':next_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)
- last_form = final_form_list[-1]
- context.update({'datas':self.get_formated_datas(final_form_list)})
- if hasattr(last_form, 'confirm_msg'):
- context.update({'confirm_msg':last_form.confirm_msg})
- if hasattr(last_form, 'confirm_end_msg'):
- context.update({'confirm_end_msg':last_form.confirm_end_msg})
- return context
-
- def get_formated_datas(self, forms):
- """Get the data to present in the last page"""
- datas = []
- for form in forms:
- form_datas = []
- 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') and hasattr(form, 'forms'):
- cleaned_datas = [frm.cleaned_data for frm in form.forms
- if frm.is_valid()]
- if not cleaned_datas:
- continue
- elif not hasattr(form, 'cleaned_data'):
- continue
- else:
- cleaned_datas = type(form.cleaned_data) == list and \
- form.cleaned_data \
- or [form.cleaned_data]
- for cleaned_data in cleaned_datas:
- if not cleaned_data:
- continue
- if form_datas:
- form_datas.append(("", "", "spacer"))
- items = hasattr(base_form, 'fields') and \
- base_form.fields.keyOrder or cleaned_data.keys()
- for key in items:
- lbl = None
- if key.startswith('hidden_'):
- continue
- if hasattr(base_form, 'fields') and key in base_form.fields:
- lbl = base_form.fields[key].label
- if hasattr(base_form, 'associated_labels') \
- and key in base_form.associated_labels:
- lbl = base_form.associated_labels[key]
- if not lbl:
- continue
- value = cleaned_data[key]
- if not value and value != False:
- continue
- if type(value) == bool:
- if value == True:
- value = _(u"Yes")
- elif value == False:
- value = _(u"No")
- elif key in associated_models:
- values = []
- if "," in unicode(value):
- values = unicode(value).split(",")
- else:
- values = [value]
- rendered_values = []
- for val in values:
- item = associated_models[key].objects.get(pk=val)
- if hasattr(item, 'short_label'):
- value = item.short_label()
- else:
- value = unicode(item)
- rendered_values.append(value)
- value = u" ; ".join(rendered_values)
- form_datas.append((lbl, value, ''))
- if form_datas:
- datas.append((form.form_label, form_datas))
- return datas
-
- def get_extra_model(self, dct, request, storage, form_list):
- dct['history_modifier'] = request.user
- return dct
-
- def done(self, request, storage, form_list, return_object=False, **kwargs):
- """Save to the model"""
- dct, m2m, whole_associated_models = {}, [], []
- for form in form_list:
- if not form.is_valid():
- return self.render(request, storage, form)
- 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 hasattr(form, 'forms'):
- multi = False
- if form.forms:
- frm = form.forms[0]
- if hasattr(frm, 'base_model') and frm.base_model:
- whole_associated_models.append(frm.base_model)
- else:
- whole_associated_models += associated_models.keys()
- fields = frm.fields.copy()
- if 'DELETE' in fields:
- fields.pop('DELETE')
- multi = len(fields) > 1
- if multi:
- assert hasattr(frm, 'base_model'), \
- u"Must define a base_model for " + unicode(frm.__class__)
- for frm in form.forms:
- if not frm.is_valid():
- continue
- vals = {}
- if "DELETE" in frm.cleaned_data:
- if frm.cleaned_data["DELETE"]:
- continue
- frm.cleaned_data.pop('DELETE')
- for key in frm.cleaned_data:
- value = frm.cleaned_data[key]
- if not value and value != False:
- continue
- if key in associated_models:
- value = associated_models[key].objects.get(pk=value)
- if multi:
- vals[key] = value
- else:
- m2m.append((key, value))
- if multi and vals:
- m2m.append((frm.base_model, vals))
- elif type(form.cleaned_data) == dict:
- for key in form.cleaned_data:
- if key.startswith('hidden_'):
- continue
- value = form.cleaned_data[key]
- if key in associated_models:
- if value:
- model = associated_models[key]
- if isinstance(value, unicode) \
- or isinstance(value, str) and "," in value:
- value = value.split(",")
- if isinstance(value, list) \
- or isinstance(value, tuple):
- value = [model.objects.get(pk=val)
- for val in value if val]
- if len(value) == 1:
- value = value[0]
- else:
- value = model.objects.get(pk=value)
- else:
- value = None
- dct[key] = value
- return self.save_model(dct, m2m, whole_associated_models, request,
- storage, form_list, return_object)
-
- def get_saved_model(self):
- """Permit a distinguo when saved model is not the base selected model"""
- return self.model
-
- def get_current_saved_object(self, request, storage):
- """Permit a distinguo when saved model is not the base selected model"""
- return self.get_current_object(request, storage)
-
- def save_model(self, dct, m2m, whole_associated_models, request, storage,
- form_list, return_object):
- dct = self.get_extra_model(dct, request, storage, form_list)
- obj = self.get_current_saved_object(request, storage)
- # manage dependant items
- other_objs = {}
- for k in dct.keys():
- if '__' not in k:
- continue
- vals = k.split('__')
- assert len(vals) == 2, "Only one level of dependant item is managed"
- dependant_item, key = vals
- if dependant_item not in other_objs:
- other_objs[dependant_item] = {}
- other_objs[dependant_item][key] = dct.pop(k)
- if obj:
- for k in dct:
- if k.startswith('pk'):
- continue
- setattr(obj, k, dct[k])
- try:
- obj.full_clean()
- except forms.ValidationError, msg:
- return self.render(request, storage, form_list[-1])
- for dependant_item in other_objs:
- c_item = getattr(obj, dependant_item)
- # manage ManyToMany if only one associated
- if hasattr(c_item, "all"):
- c_items = c_item.all()
- if len(c_items) != 1:
- continue
- c_item = c_items[0]
- if c_item:
- # to check #
- for k in other_objs[dependant_item]:
- setattr(c_item, k, other_objs[dependant_item][k])
- c_item.save()
- else:
- m = getattr(self.model, dependant_item)
- if hasattr(m, 'related'):
- c_item = m.related.model(**other_objs[dependant_item])
- setattr(obj, dependant_item, c_item)
- obj.save()
- obj.save()
- else:
- adds = {}
- for dependant_item in other_objs:
- m = getattr(self.model, dependant_item)
- model = m.field.rel.to
- c_dct = other_objs[dependant_item].copy()
- if issubclass(model, models.BaseHistorizedItem):
- c_dct['history_modifier'] = request.user
- c_item = model(**c_dct)
- c_item.save()
- if hasattr(m, 'through'):
- adds[dependant_item] = c_item
- elif hasattr(m, 'field'):
- dct[dependant_item] = c_item
- if 'pk' in dct:
- dct.pop('pk')
- obj = self.get_saved_model()(**dct)
- try:
- obj.full_clean()
- except forms.ValidationError, msg:
- return self.render(request, storage, form_list[-1])
- obj.save()
- for k in adds:
- getattr(obj, k).add(adds[k])
- # necessary to manage interaction between models like
- # material_index management for baseitems
- obj.save()
- m2m_items = {}
- for model in whole_associated_models:
- getattr(obj, model+'s').clear()
- for key, value in m2m:
- if key not in m2m_items:
- if type(key) == dict:
- vals = []
- for item in getattr(obj, key+'s').all():
- v = {}
- for k in value.keys():
- v[k] = getattr(item, k)
- vals.append(v)
- m2m_items[key] = vals
- else:
- m2m_items[key] = getattr(obj, key+'s').all()
- if value not in m2m_items[key]:
- if type(value) == dict:
- model = getattr(obj, key+'s').model
- if issubclass(model, models.BaseHistorizedItem):
- value['history_modifier'] = request.user
- value = model.objects.create(**value)
- value.save()
- getattr(obj, key+'s').add(value)
- # necessary to manage interaction between models like
- # material_index management for baseitems
- obj.save()
- res = render_to_response('wizard_done.html', {},
- context_instance=RequestContext(request))
- return return_object and (obj, res) or res
-
- def get_deleted(self, keys):
- """Get the deleted and non-deleted items in formsets"""
- not_to_delete, to_delete = set(), set()
- for key in keys:
- items = key.split('-')
- if len(items) < 2 or items[-2] in to_delete:
- continue
- idx = items[-2]
- try:
- int(idx)
- except:
- continue
- if items[-1] == u'DELETE':
- to_delete.add(idx)
- if idx in not_to_delete:
- not_to_delete.remove(idx)
- elif idx not in not_to_delete:
- not_to_delete.add(idx)
- return (to_delete, not_to_delete)
-
- 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'):
- # manage deletion
- to_delete, not_to_delete = self.get_deleted(data.keys())
- # raz deleted fields
- for key in data.keys():
- items = key.split('-')
- if len(items) < 2 or items[-2] not in to_delete:
- continue
- data.pop(key)
- if to_delete:
- # reorganize
- for idx, number in enumerate(sorted(not_to_delete)):
- idx = unicode(idx)
- if idx == number:
- continue
- for key in data.keys():
- items = key.split('-')
- if len(items) > 2 and number == items[-2]:
- items[-2] = unicode(idx)
- k = u'-'.join(items)
- data[k] = data.pop(key)[0]
- # get a form key
- base_key = form.form.base_fields.keys()[0]
- init = self.get_form_initial(request, storage, step)
- total_field = len([key for key in data.keys()
- if base_key in key.split('-')
- and data[key]])
- if init and not to_delete:
- total_field = max((total_field, len(init)))
- data[step + u'-INITIAL_FORMS'] = unicode(total_field)
- data[step + u'-TOTAL_FORMS'] = unicode(total_field + 1)
- data = data or None
- form = super(Wizard, self).get_form(request, storage, step, data, files)
- return form
-
- def render_next_step(self, request, storage, form, **kwargs):
- """
- Manage:
- - modify or delete button in formset: next step = current step
- - validate and end: nextstep = last step
- """
- if request.POST.has_key('formset_modify') \
- and request.POST['formset_modify'] \
- or [key for key in request.POST.keys()
- if key.endswith('DELETE') and request.POST[key]]:
- return self.render(request, storage, form, **kwargs)
- elif request.POST.has_key('validate_and_end') \
- and request.POST['validate_and_end']:
- last_step = self.get_last_step(request, storage)
- new_form = self.get_form(request, storage, last_step,
- data=storage.get_step_data(last_step),
- files=storage.get_step_files(last_step))
- storage.set_current_step(last_step)
- return self.render(request, storage, new_form, **kwargs)
- return super(Wizard, self).render_next_step(request, storage, form,
- **kwargs)
-
- def process_post_request(self, request, storage, *args, **kwargs):
- """Convert numerical step number to step name"""
- post_data = request.POST.copy()
- if request.POST.has_key('form_prev_step'):
- try:
- step_number = int(request.POST['form_prev_step'])
- post_data['form_prev_step'] = self.get_form_list(request,
- storage).keys()[step_number]
- except ValueError:
- pass
- request.POST = post_data
- return super(Wizard, self).process_post_request(request, storage, *args,
- **kwargs)
-
- @classmethod
- def session_has_key(cls, request, storage, form_key, key=None, multi=None):
- """Check if the session has value of a specific form and (if provided)
- of a key
- """
- test = storage.prefix in request.session \
- and 'step_data' in request.session[storage.prefix] \
- and form_key in request.session[storage.prefix]['step_data']
- if not key or not test:
- return test
- key = key.startswith(form_key) and key or \
- not multi and form_key + '-' + key or \
- form_key + '-0-' + key #only check if the first field is available
- return key in request.session[storage.prefix]['step_data'][form_key]
-
- @classmethod
- def session_get_value(cls, request, storage, form_key, key, multi=False):
- """Get the value of a specific form"""
- if not cls.session_has_key(request, storage, form_key, key, multi):
- return
- if not multi:
- key = key.startswith(form_key) and key or form_key + '-' + key
- return request.session[storage.prefix]['step_data'][form_key][key]
- vals = []
- for k in request.session[storage.prefix]['step_data'][form_key]:
- if k.startswith(form_key) and k.endswith(key) and \
- request.session[storage.prefix]['step_data'][form_key][k]:
- vals.append(request.session[storage.prefix]['step_data']\
- [form_key][k])
- return vals
-
- def get_current_object(self, request, storage):
- """Get the current object for an instancied wizard"""
- current_obj = None
- main_form_key = 'selec-' + self.url_name
- try:
- idx = int(self.session_get_value(request, storage, main_form_key,
- 'pk'))
- current_obj = self.model.objects.get(pk=idx)
- except(TypeError, ValueError, ObjectDoesNotExist):
- pass
- return current_obj
-
- def get_form_initial(self, request, storage, step):
- current_obj = self.get_current_object(request, storage)
- current_step = storage.get_current_step() or self.get_first_step(
- request, storage)
- if step.startswith('selec-') and step in self.form_list \
- and 'pk' in self.form_list[step].associated_models:
- model_name = self.form_list[step].associated_models['pk'
- ].__name__.lower()
- if step == current_step:
- self.reset_wizard(request, storage)
- val = model_name in request.session and request.session[model_name]
- if val:
- return {'pk':val}
- elif current_obj:
- return self.get_instanced_init(current_obj, request, storage,
- step)
- current_form = self.form_list[current_step]
- if hasattr(current_form, 'currents'):
- initial = {}
- for key in current_form.currents:
- model_name = current_form.currents[key].__name__.lower()
- val = model_name in request.session and \
- request.session[model_name]
- if val:
- initial[key] = val
- if initial:
- return initial
- return super(Wizard, self).get_form_initial(request, storage, step)
-
- def get_instanced_init(self, obj, request, storage, step=None):
- """Get initial data from an init"""
- current_step = step or storage.get_current_step() \
- or self.get_first_step(request, storage)
- c_form = self.form_list[current_step]
- # make the current object the default item for the session
- obj_name = obj.__class__.__name__.lower()
- # prefer a specialized name if available
- prefixes = storage.prefix.split('_')
- if len(prefixes) > 1 and prefixes[-2].startswith(obj_name):
- obj_name = prefixes[-2]
- request.session[obj_name] = unicode(obj.pk)
- initial = {}
- if request.POST or (step in request.session[storage.prefix] and\
- request.session[storage.prefix]['step_data'][step]):
- return {}
- if hasattr(c_form, 'base_fields'):
- for base_field in c_form.base_fields.keys():
- fields = base_field.split('__')
- value = obj
- for field in fields:
- if not hasattr(value, field) or \
- getattr(value, field) == None:
- value = obj
- break
- value = getattr(value, field)
- if value == obj:
- continue
- if hasattr(value, 'pk'):
- value = value.pk
- if value in (True, False):
- initial[base_field] = value
- elif value != None:
- initial[base_field] = unicode(value)
- elif hasattr(c_form, 'management_form'):
- initial = []
- if hasattr(c_form.form, 'base_model'):
- key = c_form.form.base_model + 's'
- else:
- key = current_step.split('-')[0]
- if not hasattr(obj, key):
- return initial
- keys = c_form.form.base_fields.keys()
- for child_obj in getattr(obj, key).order_by('pk').all():
- if not keys:
- break
- vals = {}
- if len(keys) == 1:
- # only one field: must be the id of the object
- vals[keys[0]] = unicode(child_obj.pk)
- else:
- for field in keys:
- if hasattr(child_obj, field):
- value = getattr(child_obj, field)
- if hasattr(value, 'pk'):
- value = value.pk
- if value != None:
- vals[field] = unicode(value)
- if vals:
- initial.append(vals)
- return initial
-
def get_now():
format = formats.get_format('DATE_INPUT_FORMATS')[0]
value = datetime.datetime.now().strftime(format)
@@ -815,4 +246,4 @@ def get_form_selection(class_name, label, key, model, base_form, get_url,
return cleaned_data
attrs['clean'] = clean
return type(class_name, (forms.Form,), attrs)
-
+'''
diff --git a/ishtar/ishtar_base/forms_common.py b/ishtar/ishtar_base/forms_common.py
index 68ab9be5f..7ef1d4070 100644
--- a/ishtar/ishtar_base/forms_common.py
+++ b/ishtar/ishtar_base/forms_common.py
@@ -38,8 +38,7 @@ from ishtar import settings
import models
import widgets
-from forms import Wizard, SearchWizard, FinalForm, FormSet, reverse_lazy, \
- name_validator
+from forms import FinalForm, FormSet, reverse_lazy, name_validator
def get_town_field(label=_(u"Town"), required=True):
help_text = _(u"<p>Type name, department code and/or postal code of the "
@@ -152,9 +151,6 @@ class OrganizationForm(forms.Form):
new_item.save()
return new_item
-class PersonWizard(Wizard):
- model = models.Person
-
class PersonFormSelection(forms.Form):
form_label = _(u"Person search")
associated_models = {'pk':models.Person}
@@ -199,14 +195,11 @@ class PersonForm(forms.Form):
new_item.save()
return new_item
+'''
person_search_wizard = SearchWizard([
('general-person_search', PersonFormSelection)],
url_name='person_search',)
-person_creation_wizard = PersonWizard([
- ('identity-person_creation', PersonForm),
- ('final-person_creation', FinalForm)],
- url_name='person_creation',)
person_modification_wizard = PersonWizard([
@@ -228,9 +221,9 @@ class AccountWizard(Wizard):
return datas
def done(self, request, storage, form_list, **kwargs):
- '''
+ """
Save the account
- '''
+ """
dct = {}
for form in form_list:
if not form.is_valid():
@@ -299,7 +292,7 @@ class AccountWizard(Wizard):
form.is_hidden = False
return form
-
+'''
class AccountForm(forms.Form):
form_label = _("Account")
associated_models = {'pk':models.Person}
@@ -355,13 +348,13 @@ class FinalAccountForm(forms.Form):
def __init__(self, *args, **kwargs):
self.is_hidden = True
return super(FinalAccountForm, self).__init__(*args, **kwargs)
-
+'''
account_management_wizard = AccountWizard([
('selec-account_management', PersonFormSelection),
('account-account_management', AccountForm),
('final-account_management', FinalAccountForm)],
url_name='account_management',)
-
+'''
class TownForm(forms.Form):
form_label = _("Towns")
base_model = 'town'
@@ -432,7 +425,7 @@ ParcelFormSet.form_label = _(u"Parcels")
######################
# Sources management #
######################
-
+'''
class SourceWizard(Wizard):
model = None
def get_extra_model(self, dct, request, storage, form_list):
@@ -441,7 +434,7 @@ class SourceWizard(Wizard):
if 'history_modifier' in dct:
dct.pop('history_modifier')
return dct
-
+'''
class SourceForm(forms.Form):
form_label = _(u"Documentation informations")
associated_models = {'source_type':models.SourceType}
diff --git a/ishtar/ishtar_base/forms_main.py b/ishtar/ishtar_base/forms_main.py
index 723b80d83..29253f284 100644
--- a/ishtar/ishtar_base/forms_main.py
+++ b/ishtar/ishtar_base/forms_main.py
@@ -18,9 +18,9 @@
# See the file COPYING for details.
from forms_common import *
-from forms_files import *
-from forms_operations import *
-from forms_context_records import *
-from forms_items import *
+#from forms_files import *
+#from forms_operations import *
+#from forms_context_records import *
+#from forms_items import *
from forms import *
diff --git a/ishtar/ishtar_base/management/commands/generate_rights.py b/ishtar/ishtar_base/management/commands/generate_rights.py
index 9bf2776a8..75b1cf807 100644
--- a/ishtar/ishtar_base/management/commands/generate_rights.py
+++ b/ishtar/ishtar_base/management/commands/generate_rights.py
@@ -17,6 +17,8 @@
# See the file COPYING for details.
+import sys
+
from django.core.management.base import BaseCommand, CommandError
from django.core.exceptions import ObjectDoesNotExist
@@ -40,7 +42,8 @@ class Command(BaseCommand):
except ObjectDoesNotExist:
wizard_obj = models.Wizard.objects.create(url_name=url_name)
wizard_obj.save()
- self.stdout.write('* Wizard "%s" added\n' % url_name)
+ #self.stdout.write('* Wizard "%s" added\n' % url_name)
+ sys.stdout.write('* Wizard "%s" added\n' % url_name)
wizard_steps[url_name] = []
for idx, step_url_name in enumerate(wizard.form_list.keys()):
form = wizard.form_list[step_url_name]
@@ -59,7 +62,10 @@ class Command(BaseCommand):
'url_name':step_url_name})
step_obj = models.WizardStep.objects.create(**step_values)
step_obj.save()
- self.stdout.write('* Wizard step "%s" added\n' \
+ #self.stdout.write('* Wizard step "%s" added\n' \
+ # % unicode(form.form_label))
+ sys.stdout.write('* Wizard step "%s" added\n' \
% unicode(form.form_label))
wizard_steps[url_name].append(step_url_name)
- self.stdout.write('Successfully regeneration of wizard rights\n')
+ #self.stdout.write('Successfully regeneration of wizard rights\n')
+ sys.stdout.write('Successfully regeneration of wizard rights\n')
diff --git a/ishtar/ishtar_base/urls.py b/ishtar/ishtar_base/urls.py
index 8f511cf39..a5b1f5efa 100644
--- a/ishtar/ishtar_base/urls.py
+++ b/ishtar/ishtar_base/urls.py
@@ -19,9 +19,10 @@
from django.conf.urls.defaults import *
-from ishtar.urls import BASE_URL
from menus import menu
-import forms_main as ishtar_forms
+#import forms_main as ishtar_forms
+
+import views
urlpatterns, actions = [], []
@@ -29,102 +30,106 @@ urlpatterns, actions = [], []
# forms
urlpatterns = patterns('',
# General
- url(BASE_URL + r'person_creation/(?P<step>.+)$',
- ishtar_forms.person_creation_wizard, name='person_creation'),
- url(BASE_URL + r'person_modification/(?P<step>.+)$',
+ url(r'person_creation/(?P<step>.+)$',
+ views.person_creation_wizard, name='person_creation_step'),
+ url(r'person_creation/$',
+ views.person_creation_wizard, name='person_creation'),
+ )
+"""
+ url(r'person_modification/(?P<step>.+)$',
ishtar_forms.person_modification_wizard, name='person_modification'),
- url(BASE_URL + r'account_management/(?P<step>.+)$',
+ url(r'account_management/(?P<step>.+)$',
ishtar_forms.account_management_wizard, name='account_management'),
# Archaelogical files
- url(BASE_URL + r'file_search/(?P<step>.+)$',
+ url(r'file_search/(?P<step>.+)$',
ishtar_forms.file_search_wizard, name='file_search'),
- url(BASE_URL + r'file_creation/(?P<step>.+)$',
+ url(r'file_creation/(?P<step>.+)$',
ishtar_forms.file_creation_wizard, name='file_creation'),
- url(BASE_URL + r'file_modification/(?P<step>.+)$',
+ url(r'file_modification/(?P<step>.+)$',
ishtar_forms.file_modification_wizard, name='file_modification'),
- url(BASE_URL + r'file_closing/(?P<step>.+)$',
+ url(r'file_closing/(?P<step>.+)$',
ishtar_forms.file_closing_wizard, name='file_closing'),
- url(BASE_URL + r'file_deletion/(?P<step>.+)$',
+ url(r'file_deletion/(?P<step>.+)$',
ishtar_forms.file_deletion_wizard, name='file_deletion'),
- url(BASE_URL + r'file_administrativeactfile/(?P<step>.+)$',
+ url(r'file_administrativeactfile/(?P<step>.+)$',
ishtar_forms.file_administrativeactfile_wizard,
name='file_administrativeactfile'),
- url(BASE_URL + r'file_administrativeactfile_modification/(?P<step>.+)$',
+ url(r'file_administrativeactfile_modification/(?P<step>.+)$',
ishtar_forms.file_administrativeactfile_modification_wizard,
name='file_administrativeactfile_modification'),
- url(BASE_URL + r'file_administrativeactfile_deletion/(?P<step>.+)$',
+ url(r'file_administrativeactfile_deletion/(?P<step>.+)$',
ishtar_forms.file_administrativeactfile_deletion_wizard,
name='file_administrativeactfile_deletion'),
# Operations
- url(BASE_URL + r'operation_search/(?P<step>.+)$',
+ url(r'operation_search/(?P<step>.+)$',
ishtar_forms.operation_search_wizard, name='operation_search'),
- url(BASE_URL + r'operation_creation/(?P<step>.+)$',
+ url(r'operation_creation/(?P<step>.+)$',
ishtar_forms.operation_creation_wizard, name='operation_creation'),
- url(BASE_URL + r'operation_modification/(?P<step>.+)$',
+ url(r'operation_modification/(?P<step>.+)$',
ishtar_forms.operation_modification_wizard,
name='operation_modification'),
- url(BASE_URL + r'operation_closing/(?P<step>.+)$',
+ url(r'operation_closing/(?P<step>.+)$',
ishtar_forms.operation_closing_wizard, name='operation_closing'),
- url(BASE_URL + r'operation_deletion/(?P<step>.+)$',
+ url(r'operation_deletion/(?P<step>.+)$',
ishtar_forms.operation_deletion_wizard, name='operation_deletion'),
- url(BASE_URL + r'operation_administrativeactop/(?P<step>.+)$',
+ url(r'operation_administrativeactop/(?P<step>.+)$',
ishtar_forms.operation_administrativeactop_wizard,
name='operation_administrativeactop'),
- url(BASE_URL + r'operation_administrativeactop_modification/(?P<step>.+)$',
+ url(r'operation_administrativeactop_modification/(?P<step>.+)$',
ishtar_forms.operation_administrativeactop_modification_wizard,
name='operation_administrativeactop_modification'),
- url(BASE_URL + r'operation_administrativeactop_deletion/(?P<step>.+)$',
+ url(r'operation_administrativeactop_deletion/(?P<step>.+)$',
ishtar_forms.operation_administrativeactop_deletion_wizard,
name='operation_administrativeactop_deletion'),
- url(BASE_URL + r'operation_source_creation/(?P<step>.+)$',
+ url(r'operation_source_creation/(?P<step>.+)$',
ishtar_forms.operation_source_creation_wizard,
name='operation_source_creation'),
- url(BASE_URL + r'operation_source_modification/(?P<step>.+)$',
+ url(r'operation_source_modification/(?P<step>.+)$',
ishtar_forms.operation_source_modification_wizard,
name='operation_source_modification'),
- url(BASE_URL + r'operation_source_deletion/(?P<step>.+)$',
+ url(r'operation_source_deletion/(?P<step>.+)$',
ishtar_forms.operation_source_deletion_wizard,
name='operation_source_deletion'),
# Context records
- url(BASE_URL + r'record_search/(?P<step>.+)$',
+ url(r'record_search/(?P<step>.+)$',
ishtar_forms.record_search_wizard, name='record_search'),
- url(BASE_URL + r'record_creation/(?P<step>.+)$',
+ url(r'record_creation/(?P<step>.+)$',
ishtar_forms.record_creation_wizard, name='record_creation'),
- url(BASE_URL + r'record_modification/(?P<step>.+)$',
+ url(r'record_modification/(?P<step>.+)$',
ishtar_forms.record_modification_wizard, name='record_modification'),
- url(BASE_URL + r'record_deletion/(?P<step>.+)$',
+ url(r'record_deletion/(?P<step>.+)$',
ishtar_forms.record_deletion_wizard, name='record_deletion'),
- url(BASE_URL + r'record_source_creation/(?P<step>.+)$',
+ url(r'record_source_creation/(?P<step>.+)$',
ishtar_forms.record_source_creation_wizard,
name='record_source_creation'),
- url(BASE_URL + r'record_source_modification/(?P<step>.+)$',
+ url(r'record_source_modification/(?P<step>.+)$',
ishtar_forms.record_source_modification_wizard,
name='record_source_modification'),
- url(BASE_URL + r'record_source_deletion/(?P<step>.+)$',
+ url(r'record_source_deletion/(?P<step>.+)$',
ishtar_forms.record_source_deletion_wizard,
name='record_source_deletion'),
# Finds
- url(BASE_URL + r'item_search/(?P<step>.+)$',
+ url(r'item_search/(?P<step>.+)$',
ishtar_forms.item_search_wizard, name='item_search'),
- url(BASE_URL + r'item_creation/(?P<step>.+)$',
+ url(r'item_creation/(?P<step>.+)$',
ishtar_forms.item_creation_wizard, name='item_creation'),
- url(BASE_URL + r'item_modification/(?P<step>.+)$',
+ url(r'item_modification/(?P<step>.+)$',
ishtar_forms.item_modification_wizard, name='item_modification'),
- url(BASE_URL + r'item_source_creation/(?P<step>.+)$',
+ url(r'item_source_creation/(?P<step>.+)$',
ishtar_forms.item_source_creation_wizard,
name='item_source_creation'),
- url(BASE_URL + r'item_source_modification/(?P<step>.+)$',
+ url(r'item_source_modification/(?P<step>.+)$',
ishtar_forms.item_source_modification_wizard,
name='item_source_modification'),
- url(BASE_URL + r'item_source_deletion/(?P<step>.+)$',
+ url(r'item_source_deletion/(?P<step>.+)$',
ishtar_forms.item_source_deletion_wizard,
name='item_source_deletion'),
# Treatments
- url(BASE_URL + r'treatment_creation/(?P<step>.+)$',
+ url(r'treatment_creation/(?P<step>.+)$',
ishtar_forms.treatment_creation_wizard, name='treatment_creation'),
- url(BASE_URL + r'warehouse_packaging/(?P<step>.+)$',
+ url(r'warehouse_packaging/(?P<step>.+)$',
ishtar_forms.warehouse_packaging_wizard, name='warehouse_packaging'),
- )
+ )"""
for section in menu.childs:
for menu_item in section.childs:
if hasattr(menu_item, 'childs'):
@@ -137,82 +142,82 @@ actions = r"|".join(actions)
# other views
urlpatterns += patterns('ishtar.ishtar_base.views',
# General
- url(BASE_URL + r'(?P<action_slug>' + actions + r')/$', 'action',
+ url(r'(?P<action_slug>' + actions + r')/$', 'action',
name='action'),
- url(BASE_URL + r'new-person/(?P<parent_name>.+)?/$',
+ url(r'new-person/(?P<parent_name>.+)?/$',
'new_person', name='new-person'),
- url(BASE_URL + r'autocomplete-person/([0-9_]+)?$', 'autocomplete_person',
+ url(r'autocomplete-person/([0-9_]+)?$', 'autocomplete_person',
name='autocomplete-person'),
- url(BASE_URL + r'autocomplete-town/$', 'autocomplete_town',
+ url(r'autocomplete-town/$', 'autocomplete_town',
name='autocomplete-town'),
- url(BASE_URL + r'new-author/(?P<parent_name>.+)?/$',
+ url(r'new-author/(?P<parent_name>.+)?/$',
'new_author', name='new-author'),
- url(BASE_URL + r'autocomplete-author/$', 'autocomplete_author',
+ url(r'autocomplete-author/$', 'autocomplete_author',
name='autocomplete-author'),
- url(BASE_URL + r'new-organization/(?P<parent_name>.+)?/$',
+ url(r'new-organization/(?P<parent_name>.+)?/$',
'new_organization', name='new-organization'),
- url(BASE_URL + r'autocomplete-organization/([0-9_]+)?$',
+ url(r'autocomplete-organization/([0-9_]+)?$',
'autocomplete_organization', name='autocomplete-organization'),
- url(BASE_URL + r'new-warehouse/(?P<parent_name>.+)?/$',
+ url(r'new-warehouse/(?P<parent_name>.+)?/$',
'new_warehouse', name='new-warehouse'),
- url(BASE_URL + r'autocomplete-warehouse/$', 'autocomplete_warehouse',
+ url(r'autocomplete-warehouse/$', 'autocomplete_warehouse',
name='autocomplete-warehouse'),
# Archaelogical files
- url(BASE_URL + r'autocomplete-file/$', 'autocomplete_file',
+ url(r'autocomplete-file/$', 'autocomplete_file',
name='autocomplete-file'),
- url(BASE_URL + r'get-file/(?P<type>.+)?$', 'get_file',
+ url(r'get-file/(?P<type>.+)?$', 'get_file',
name='get-file'),
- url(BASE_URL + r'get-file-full/(?P<type>.+)?$', 'get_file',
+ url(r'get-file-full/(?P<type>.+)?$', 'get_file',
name='get-file-full', kwargs={'full':True}),
- url(BASE_URL + r'get-administrativeactfile/(?P<type>.+)?$',
+ url(r'get-administrativeactfile/(?P<type>.+)?$',
'get_administrativeactfile', name='get-administrativeactfile'),
- url(BASE_URL + r'show-file/(?P<pk>.+)?/(?P<type>.+)?$', 'show_file',
+ url(r'show-file/(?P<pk>.+)?/(?P<type>.+)?$', 'show_file',
name='show-file'),
- url(BASE_URL + r'show-historized-file/(?P<pk>.+)?/(?P<date>.+)?$',
+ url(r'show-historized-file/(?P<pk>.+)?/(?P<date>.+)?$',
'show_file', name='show-historized-file'),
- url(BASE_URL + r'revert-file/(?P<pk>.+)/(?P<date>.+)$',
+ url(r'revert-file/(?P<pk>.+)/(?P<date>.+)$',
'revert_file', name='revert-file'),
# Operations
- url(BASE_URL + r'autocomplete-operation/$', 'autocomplete_operation',
+ url(r'autocomplete-operation/$', 'autocomplete_operation',
name='autocomplete-operation'),
- url(BASE_URL + r'get-operation/(?P<type>.+)?$', 'get_operation',
+ url(r'get-operation/(?P<type>.+)?$', 'get_operation',
name='get-operation'),
- url(BASE_URL + r'get-operation-full/(?P<type>.+)?$', 'get_operation',
+ url(r'get-operation-full/(?P<type>.+)?$', 'get_operation',
name='get-operation-full', kwargs={'full':True}),
- url(BASE_URL + r'get-available-operation-code/(?P<year>.+)?$',
+ url(r'get-available-operation-code/(?P<year>.+)?$',
'get_available_operation_code', name='get_available_operation_code'),
- url(BASE_URL + r'revert-operation/(?P<pk>.+)/(?P<date>.+)$',
+ url(r'revert-operation/(?P<pk>.+)/(?P<date>.+)$',
'revert_operation', name='revert-operation'),
- url(BASE_URL + r'show-operation/(?P<pk>.+)?/(?P<type>.+)?$',
+ url(r'show-operation/(?P<pk>.+)?/(?P<type>.+)?$',
'show_operation', name='show-operation'),
- url(BASE_URL + r'get-administrativeactop/(?P<type>.+)?$',
+ url(r'get-administrativeactop/(?P<type>.+)?$',
'get_administrativeactop', name='get-administrativeactop'),
- url(BASE_URL + r'get-operationsource/(?P<type>.+)?$',
+ url(r'get-operationsource/(?P<type>.+)?$',
'get_operationsource', name='get-operationsource'),
# Context records
- url(BASE_URL + r'show-contextrecord/(?P<pk>.+)?/(?P<type>.+)?$',
+ url(r'show-contextrecord/(?P<pk>.+)?/(?P<type>.+)?$',
'show_contextrecord', name='show-contextrecord'),
- url(BASE_URL + r'get-contextrecord/(?P<type>.+)?$', 'get_contextrecord',
+ url(r'get-contextrecord/(?P<type>.+)?$', 'get_contextrecord',
name='get-contextrecord'),
- url(BASE_URL + r'get-contextrecord-full/(?P<type>.+)?$',
+ url(r'get-contextrecord-full/(?P<type>.+)?$',
'get_contextrecord', name='get-contextrecord-full',
kwargs={'full':True}),
- url(BASE_URL + r'get-contexrecordsource/(?P<type>.+)?$',
+ url(r'get-contexrecordsource/(?P<type>.+)?$',
'get_contextrecordsource', name='get-contextrecordsource'),
# Finds
- url(BASE_URL + r'update-current-item/$', 'update_current_item',
+ url(r'update-current-item/$', 'update_current_item',
name='update-current-item'),
- url(BASE_URL + r'get-item/(?P<type>.+)?$', 'get_archaeologicalitem',
+ url(r'get-item/(?P<type>.+)?$', 'get_archaeologicalitem',
name='get-item'),
- url(BASE_URL + r'get-item-full/(?P<type>.+)?$', 'get_archaeologicalitem',
+ url(r'get-item-full/(?P<type>.+)?$', 'get_archaeologicalitem',
name='get-item-full', kwargs={'full':True}),
- url(BASE_URL + r'get-itemsource/(?P<type>.+)?$',
+ url(r'get-itemsource/(?P<type>.+)?$',
'get_itemsource', name='get-itemsource'),
- url(BASE_URL + r'get-container/$', 'get_container',
+ url(r'get-container/$', 'get_container',
name='get-container'),
# Treatments
- url(BASE_URL + r'autocomplete-container/?$',
+ url(r'autocomplete-container/?$',
'autocomplete_container', name='autocomplete-container'),
- url(BASE_URL + r'new-container/(?P<parent_name>.+)?/$',
+ url(r'new-container/(?P<parent_name>.+)?/$',
'new_container', name='new-container'),
)
diff --git a/ishtar/ishtar_base/views.py b/ishtar/ishtar_base/views.py
index 94a37d46e..4a7f276fb 100644
--- a/ishtar/ishtar_base/views.py
+++ b/ishtar/ishtar_base/views.py
@@ -17,7 +17,11 @@
# See the file COPYING for details.
-import tidy
+try:
+ import tidy
+except:
+ from tidylib import tidy_document as tidy
+
import re
import csv
import json
@@ -27,15 +31,16 @@ import cStringIO as StringIO
from tempfile import NamedTemporaryFile
import ho.pisa as pisa
+from django.contrib.formtools.wizard.views import NamedUrlWizardView
+from django.core import serializers
+from django.core.exceptions import ObjectDoesNotExist
+from django.core.urlresolvers import reverse, NoReverseMatch
+from django.db.models import Q
from django.http import HttpResponse, Http404
+from django.shortcuts import render_to_response, redirect
from django.template import RequestContext, loader
from django.template.defaultfilters import slugify
-from django.shortcuts import render_to_response, redirect
from django.utils.translation import ugettext, ugettext_lazy as _
-from django.core.exceptions import ObjectDoesNotExist
-from django.core.urlresolvers import reverse, NoReverseMatch
-from django.db.models import Q
-from django.core import serializers
from ishtar import settings
if settings.XHTML2ODT_PATH:
@@ -45,6 +50,9 @@ if settings.XHTML2ODT_PATH:
from menus import menu
import forms_main as ishtar_forms
+
+from ishtar.ishtar_base.forms import FinalForm
+from ishtar.ishtar_base.forms_common import PersonForm
import models
CSV_OPTIONS = {'delimiter':';', 'quotechar':'"', 'quoting':csv.QUOTE_ALL}
@@ -58,6 +66,613 @@ def index(request):
return render_to_response('index.html', dct,
context_instance=RequestContext(request))
+class Wizard(NamedUrlWizardView):
+ model = None
+ modification = None # True when the wizard modify an item
+ storage_name = 'django.contrib.formtools.wizard.storage.session.SessionStorage'
+
+ @staticmethod
+ def _check_right(step, condition=True):
+ '''Return a method to check the right for a specific step'''
+ """
+ def check_right(self, request, storage):
+ cond = condition
+ if callable(condition):
+ cond = condition(self, request, storage)
+ if not cond:
+ return False
+ person_type = request.user.ishtaruser.person.person_type
+ if person_type.txt_idx == 'administrator':
+ return True
+ if person_type.rights.filter(url_name=step).count():
+ return True"""
+ def check_right(self):
+ cond = condition
+ if callable(condition):
+ cond = condition(self)
+ if not cond:
+ return False
+ person_type = self.request.user.ishtaruser.person.person_type
+ if person_type.txt_idx == 'administrator':
+ return True
+ if person_type.rights.filter(url_name=step).count():
+ return True
+ return check_right
+
+ def __init__(self, *args, **kwargs):
+ """Check right for each step of the wizard"""
+ super(Wizard, self).__init__(*args, **kwargs)
+ for form_key in self.form_list.keys()[:-1]:
+ condition = True
+ if form_key in self.condition_dict:
+ condition = self.condition_dict.get(form_key, True)
+ cond = self._check_right(form_key, condition)
+ self.condition_dict[form_key] = cond
+ """
+ for form_key in self.form_list.keys()[:-1]:
+ condition = True
+ if form_key in self.condition_list:
+ condition = self.condition_list.get(form_key, True)
+ cond = self._check_right(form_key, condition)
+ self.condition_list[form_key] = cond"""
+
+ def get_wizard_name(self):
+ """As the class name can interfere when reused, use the url_name"""
+ return self.url_name
+
+ def get_template_names(self):
+ templates = ['ishtar/wizard/default_wizard.html']
+ current_step = self.steps.current
+ if current_step == self.steps.last:
+ templates = ['ishtar/wizard/confirm_wizard.html'] + templates
+ return templates
+
+ def get_context_data(self, form, **kwargs):
+ """Add previous, next and current steps to manage the wizard path"""
+ context = super(Wizard, self).get_context_data(form)
+ step = self.steps.first
+ current_step = self.steps.current
+ context.update({'current_step':self.form_list[current_step]})
+ if step == current_step:
+ return context
+ previous_steps, next_steps, previous_step_counter = [], [], 0
+ while step:
+ if step == current_step:
+ break
+ previous_steps.append(self.form_list[step])
+ step = self.steps.next
+ previous_step_counter += 1
+ context.update({'previous_steps':previous_steps,
+ 'previous_step_counter':previous_step_counter})
+ # if modification: show the next steps
+ if self.modification:
+ next_step = step
+ while next_step:
+ # check if the form is initialized otherwise initialize it
+ if not storage.get_step_data(next_step):
+ values = self.get_form_initial(request, storage, next_step)
+ prefixed_values = {}
+ if not isinstance(values, list):
+ for key in values:
+ form_key = next_step + '-' + key
+ prefixed_values[form_key] = values[key]
+ else:
+ for formset_idx, v in enumerate(values):
+ prefix = u"-%d-" % formset_idx
+ for key in v:
+ form_key = next_step + prefix + key
+ prefixed_values[form_key] = v[key]
+ storage.set_step_data(next_step, prefixed_values)
+ if step != next_step: # if not current step
+ next_steps.append(self.form_list[next_step])
+ next_step = self.get_next_step(request, storage, next_step)
+ context.update({'next_steps':next_steps})
+ # not last step: validation
+ if current_step != self.steps.last:
+ return context
+ final_form_list = []
+ for form_key in self.get_form_list().keys():
+ form_obj = self.get_form(step=form_key,
+ data=self.storage.get_step_data(form_key),
+ files=self.storage.get_step_files(form_key))
+ form_obj.is_valid()
+ final_form_list.append(form_obj)
+ last_form = final_form_list[-1]
+ context.update({'datas':self.get_formated_datas(final_form_list)})
+ if hasattr(last_form, 'confirm_msg'):
+ context.update({'confirm_msg':last_form.confirm_msg})
+ if hasattr(last_form, 'confirm_end_msg'):
+ context.update({'confirm_end_msg':last_form.confirm_end_msg})
+ return context
+
+ def get_formated_datas(self, forms):
+ """Get the data to present in the last page"""
+ datas = []
+ for form in forms:
+ form_datas = []
+ 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') and hasattr(form, 'forms'):
+ cleaned_datas = [frm.cleaned_data for frm in form.forms
+ if frm.is_valid()]
+ if not cleaned_datas:
+ continue
+ elif not hasattr(form, 'cleaned_data'):
+ continue
+ else:
+ cleaned_datas = type(form.cleaned_data) == list and \
+ form.cleaned_data \
+ or [form.cleaned_data]
+ for cleaned_data in cleaned_datas:
+ if not cleaned_data:
+ continue
+ if form_datas:
+ form_datas.append(("", "", "spacer"))
+ items = hasattr(base_form, 'fields') and \
+ base_form.fields.keyOrder or cleaned_data.keys()
+ for key in items:
+ lbl = None
+ if key.startswith('hidden_'):
+ continue
+ if hasattr(base_form, 'fields') and key in base_form.fields:
+ lbl = base_form.fields[key].label
+ if hasattr(base_form, 'associated_labels') \
+ and key in base_form.associated_labels:
+ lbl = base_form.associated_labels[key]
+ if not lbl:
+ continue
+ value = cleaned_data[key]
+ if not value and value != False:
+ continue
+ if type(value) == bool:
+ if value == True:
+ value = _(u"Yes")
+ elif value == False:
+ value = _(u"No")
+ elif key in associated_models:
+ values = []
+ if "," in unicode(value):
+ values = unicode(value).split(",")
+ else:
+ values = [value]
+ rendered_values = []
+ for val in values:
+ item = associated_models[key].objects.get(pk=val)
+ if hasattr(item, 'short_label'):
+ value = item.short_label()
+ else:
+ value = unicode(item)
+ rendered_values.append(value)
+ value = u" ; ".join(rendered_values)
+ form_datas.append((lbl, value, ''))
+ if form_datas:
+ datas.append((form.form_label, form_datas))
+ return datas
+
+ def get_extra_model(self, dct, form_list):
+ dct['history_modifier'] = self.request.user
+ return dct
+
+ def done(self, form_list, return_object=False, **kwargs):
+ """Save to the model"""
+ dct, m2m, whole_associated_models = {}, [], []
+ for form in form_list:
+ if not form.is_valid():
+ return self.render(form)
+ 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 hasattr(form, 'forms'):
+ multi = False
+ if form.forms:
+ frm = form.forms[0]
+ if hasattr(frm, 'base_model') and frm.base_model:
+ whole_associated_models.append(frm.base_model)
+ else:
+ whole_associated_models += associated_models.keys()
+ fields = frm.fields.copy()
+ if 'DELETE' in fields:
+ fields.pop('DELETE')
+ multi = len(fields) > 1
+ if multi:
+ assert hasattr(frm, 'base_model'), \
+ u"Must define a base_model for " + unicode(frm.__class__)
+ for frm in form.forms:
+ if not frm.is_valid():
+ continue
+ vals = {}
+ if "DELETE" in frm.cleaned_data:
+ if frm.cleaned_data["DELETE"]:
+ continue
+ frm.cleaned_data.pop('DELETE')
+ for key in frm.cleaned_data:
+ value = frm.cleaned_data[key]
+ if not value and value != False:
+ continue
+ if key in associated_models:
+ value = associated_models[key].objects.get(pk=value)
+ if multi:
+ vals[key] = value
+ else:
+ m2m.append((key, value))
+ if multi and vals:
+ m2m.append((frm.base_model, vals))
+ elif type(form.cleaned_data) == dict:
+ for key in form.cleaned_data:
+ if key.startswith('hidden_'):
+ continue
+ value = form.cleaned_data[key]
+ if key in associated_models:
+ if value:
+ model = associated_models[key]
+ if isinstance(value, unicode) \
+ or isinstance(value, str) and "," in value:
+ value = value.split(",")
+ if isinstance(value, list) \
+ or isinstance(value, tuple):
+ value = [model.objects.get(pk=val)
+ for val in value if val]
+ if len(value) == 1:
+ value = value[0]
+ else:
+ value = model.objects.get(pk=value)
+ else:
+ value = None
+ dct[key] = value
+ return self.save_model(dct, m2m, whole_associated_models, form_list,
+ return_object)
+
+ def get_saved_model(self):
+ """Permit a distinguo when saved model is not the base selected model"""
+ return self.model
+
+ def get_current_saved_object(self):
+ """Permit a distinguo when saved model is not the base selected model"""
+ return self.get_current_object()
+
+ def save_model(self, dct, m2m, whole_associated_models, form_list,
+ return_object):
+ dct = self.get_extra_model(dct, form_list)
+ obj = self.get_current_saved_object()
+ # manage dependant items
+ other_objs = {}
+ for k in dct.keys():
+ if '__' not in k:
+ continue
+ vals = k.split('__')
+ assert len(vals) == 2, "Only one level of dependant item is managed"
+ dependant_item, key = vals
+ if dependant_item not in other_objs:
+ other_objs[dependant_item] = {}
+ other_objs[dependant_item][key] = dct.pop(k)
+ if obj:
+ for k in dct:
+ if k.startswith('pk'):
+ continue
+ setattr(obj, k, dct[k])
+ try:
+ obj.full_clean()
+ except forms.ValidationError, msg:
+ return self.render(form_list[-1])
+ for dependant_item in other_objs:
+ c_item = getattr(obj, dependant_item)
+ # manage ManyToMany if only one associated
+ if hasattr(c_item, "all"):
+ c_items = c_item.all()
+ if len(c_items) != 1:
+ continue
+ c_item = c_items[0]
+ if c_item:
+ # to check #
+ for k in other_objs[dependant_item]:
+ setattr(c_item, k, other_objs[dependant_item][k])
+ c_item.save()
+ else:
+ m = getattr(self.model, dependant_item)
+ if hasattr(m, 'related'):
+ c_item = m.related.model(**other_objs[dependant_item])
+ setattr(obj, dependant_item, c_item)
+ obj.save()
+ obj.save()
+ else:
+ adds = {}
+ for dependant_item in other_objs:
+ m = getattr(self.model, dependant_item)
+ model = m.field.rel.to
+ c_dct = other_objs[dependant_item].copy()
+ if issubclass(model, models.BaseHistorizedItem):
+ c_dct['history_modifier'] = self.request.user
+ c_item = model(**c_dct)
+ c_item.save()
+ if hasattr(m, 'through'):
+ adds[dependant_item] = c_item
+ elif hasattr(m, 'field'):
+ dct[dependant_item] = c_item
+ if 'pk' in dct:
+ dct.pop('pk')
+ obj = self.get_saved_model()(**dct)
+ try:
+ obj.full_clean()
+ except forms.ValidationError, msg:
+ return self.render(form_list[-1])
+ obj.save()
+ for k in adds:
+ getattr(obj, k).add(adds[k])
+ # necessary to manage interaction between models like
+ # material_index management for baseitems
+ obj.save()
+ m2m_items = {}
+ for model in whole_associated_models:
+ getattr(obj, model+'s').clear()
+ for key, value in m2m:
+ if key not in m2m_items:
+ if type(key) == dict:
+ vals = []
+ for item in getattr(obj, key+'s').all():
+ v = {}
+ for k in value.keys():
+ v[k] = getattr(item, k)
+ vals.append(v)
+ m2m_items[key] = vals
+ else:
+ m2m_items[key] = getattr(obj, key+'s').all()
+ if value not in m2m_items[key]:
+ if type(value) == dict:
+ model = getattr(obj, key+'s').model
+ if issubclass(model, models.BaseHistorizedItem):
+ value['history_modifier'] = self.request.user
+ value = model.objects.create(**value)
+ value.save()
+ getattr(obj, key+'s').add(value)
+ # necessary to manage interaction between models like
+ # material_index management for baseitems
+ obj.save()
+ res = render_to_response('wizard_done.html', {},
+ context_instance=RequestContext(self.request))
+ return return_object and (obj, res) or res
+
+ def get_deleted(self, keys):
+ """Get the deleted and non-deleted items in formsets"""
+ not_to_delete, to_delete = set(), set()
+ for key in keys:
+ items = key.split('-')
+ if len(items) < 2 or items[-2] in to_delete:
+ continue
+ idx = items[-2]
+ try:
+ int(idx)
+ except:
+ continue
+ if items[-1] == u'DELETE':
+ to_delete.add(idx)
+ if idx in not_to_delete:
+ not_to_delete.remove(idx)
+ elif idx not in not_to_delete:
+ not_to_delete.add(idx)
+ return (to_delete, not_to_delete)
+
+ def get_form(self, step=None, data=None, files=None):
+ """Manage formset"""
+ request = self.request
+ storage = self.storage
+ if data:
+ data = data.copy()
+ if not step:
+ step = self.steps.current
+ form = self.get_form_list()[step]
+ if hasattr(form, 'management_form'):
+ # manage deletion
+ to_delete, not_to_delete = self.get_deleted(data.keys())
+ # raz deleted fields
+ for key in data.keys():
+ items = key.split('-')
+ if len(items) < 2 or items[-2] not in to_delete:
+ continue
+ data.pop(key)
+ if to_delete:
+ # reorganize
+ for idx, number in enumerate(sorted(not_to_delete)):
+ idx = unicode(idx)
+ if idx == number:
+ continue
+ for key in data.keys():
+ items = key.split('-')
+ if len(items) > 2 and number == items[-2]:
+ items[-2] = unicode(idx)
+ k = u'-'.join(items)
+ data[k] = data.pop(key)[0]
+ # get a form key
+ base_key = form.form.base_fields.keys()[0]
+ init = self.get_form_initial(request, storage, step)
+ total_field = len([key for key in data.keys()
+ if base_key in key.split('-')
+ and data[key]])
+ if init and not to_delete:
+ total_field = max((total_field, len(init)))
+ data[step + u'-INITIAL_FORMS'] = unicode(total_field)
+ data[step + u'-TOTAL_FORMS'] = unicode(total_field + 1)
+ data = data or None
+ form = super(Wizard, self).get_form(step, data, files)
+ return form
+
+ def render_next_step(self, form, **kwargs):
+ """
+ Manage:
+ - modify or delete button in formset: next step = current step
+ - validate and end: nextstep = last step
+ """
+ request = self.request
+ if request.POST.has_key('formset_modify') \
+ and request.POST['formset_modify'] \
+ or [key for key in request.POST.keys()
+ if key.endswith('DELETE') and request.POST[key]]:
+ return self.render(form)
+ elif request.POST.has_key('validate_and_end') \
+ and request.POST['validate_and_end']:
+ last_step = self.steps.last
+ new_form = self.get_form(last_step,
+ data=self.storage.get_step_data(last_step),
+ files=self.storage.get_step_files(last_step))
+ self.storage.current_step = last_step
+ return self.render(new_form)
+ return super(Wizard, self).render_next_step(form, **kwargs)
+
+ def post(self, *args, **kwargs):
+ """Convert numerical step number to step name"""
+ request = self.request
+ post_data = request.POST.copy()
+ if request.POST.has_key('form_prev_step'):
+ try:
+ step_number = int(request.POST['form_prev_step'])
+ post_data['wizard_goto_step'] = self.get_form_list().keys(
+ )[step_number]
+ except ValueError:
+ pass
+ request.POST = post_data
+ return super(Wizard, self).post(*args, **kwargs)
+
+ @classmethod
+ def session_has_key(cls, request, storage, form_key, key=None, multi=None):
+ """Check if the session has value of a specific form and (if provided)
+ of a key
+ """
+ test = storage.prefix in request.session \
+ and 'step_data' in request.session[storage.prefix] \
+ and form_key in request.session[storage.prefix]['step_data']
+ if not key or not test:
+ return test
+ key = key.startswith(form_key) and key or \
+ not multi and form_key + '-' + key or \
+ form_key + '-0-' + key #only check if the first field is available
+ return key in request.session[storage.prefix]['step_data'][form_key]
+
+ @classmethod
+ def session_get_value(cls, request, storage, form_key, key, multi=False):
+ """Get the value of a specific form"""
+ if not cls.session_has_key(request, storage, form_key, key, multi):
+ return
+ if not multi:
+ key = key.startswith(form_key) and key or form_key + '-' + key
+ return request.session[storage.prefix]['step_data'][form_key][key]
+ vals = []
+ for k in request.session[storage.prefix]['step_data'][form_key]:
+ if k.startswith(form_key) and k.endswith(key) and \
+ request.session[storage.prefix]['step_data'][form_key][k]:
+ vals.append(request.session[storage.prefix]['step_data']\
+ [form_key][k])
+ return vals
+
+ def get_current_object(self):
+ """Get the current object for an instancied wizard"""
+ current_obj = None
+ main_form_key = 'selec-' + self.url_name
+ try:
+ idx = int(self.session_get_value(self.request, self.storage,
+ main_form_key, 'pk'))
+ current_obj = self.model.objects.get(pk=idx)
+ except(TypeError, ValueError, ObjectDoesNotExist):
+ pass
+ return current_obj
+
+ def get_form_initial(self, step):
+ current_obj = self.get_current_object()
+ current_step = self.steps.current
+ if step.startswith('selec-') and step in self.form_list \
+ and 'pk' in self.form_list[step].associated_models:
+ model_name = self.form_list[step].associated_models['pk'
+ ].__name__.lower()
+ if step == current_step:
+ self.reset_wizard(request, storage)
+ val = model_name in request.session and request.session[model_name]
+ if val:
+ return {'pk':val}
+ elif current_obj:
+ return self.get_instanced_init(current_obj, step)
+ current_form = self.form_list[current_step]
+ if hasattr(current_form, 'currents'):
+ initial = {}
+ for key in current_form.currents:
+ model_name = current_form.currents[key].__name__.lower()
+ val = model_name in request.session and \
+ request.session[model_name]
+ if val:
+ initial[key] = val
+ if initial:
+ return initial
+ return super(Wizard, self).get_form_initial(step)
+
+ def get_instanced_init(self, obj, step=None):
+ """Get initial data from an init"""
+ current_step = step or self.steps.current
+ c_form = self.form_list[current_step]
+ # make the current object the default item for the session
+ obj_name = obj.__class__.__name__.lower()
+ # prefer a specialized name if available
+ prefixes = self.storage.prefix.split('_')
+ if len(prefixes) > 1 and prefixes[-2].startswith(obj_name):
+ obj_name = prefixes[-2]
+ self.request.session[obj_name] = unicode(obj.pk)
+ initial = {}
+ if self.request.POST or \
+ (step in self.request.session[self.storage.prefix] and\
+ self.request.session[self.storage.prefix]['step_data'][step]):
+ return {}
+ if hasattr(c_form, 'base_fields'):
+ for base_field in c_form.base_fields.keys():
+ fields = base_field.split('__')
+ value = obj
+ for field in fields:
+ if not hasattr(value, field) or \
+ getattr(value, field) == None:
+ value = obj
+ break
+ value = getattr(value, field)
+ if value == obj:
+ continue
+ if hasattr(value, 'pk'):
+ value = value.pk
+ if value in (True, False):
+ initial[base_field] = value
+ elif value != None:
+ initial[base_field] = unicode(value)
+ elif hasattr(c_form, 'management_form'):
+ initial = []
+ if hasattr(c_form.form, 'base_model'):
+ key = c_form.form.base_model + 's'
+ else:
+ key = current_step.split('-')[0]
+ if not hasattr(obj, key):
+ return initial
+ keys = c_form.form.base_fields.keys()
+ for child_obj in getattr(obj, key).order_by('pk').all():
+ if not keys:
+ break
+ vals = {}
+ if len(keys) == 1:
+ # only one field: must be the id of the object
+ vals[keys[0]] = unicode(child_obj.pk)
+ else:
+ for field in keys:
+ if hasattr(child_obj, field):
+ value = getattr(child_obj, field)
+ if hasattr(value, 'pk'):
+ value = value.pk
+ if value != None:
+ vals[field] = unicode(value)
+ if vals:
+ initial.append(vals)
+ return initial
+
+class PersonWizard(Wizard):
+ model = models.Person
+
+person_creation_wizard = PersonWizard.as_view([
+ ('identity-person_creation', PersonForm),
+ ('final-person_creation', FinalForm)],
+ url_name='person_creation_step',)
+
+
def update_current_item(request):
if not request.is_ajax() and not request.method == 'POST':
raise Http404
diff --git a/ishtar/templates/confirm_wizard.html b/ishtar/templates/ishtar/wizard/confirm_wizard.html
index 371de39c3..bd80e3967 100644
--- a/ishtar/templates/confirm_wizard.html
+++ b/ishtar/templates/ishtar/wizard/confirm_wizard.html
@@ -19,9 +19,10 @@
{% endfor %}
</table>
{% endfor %}
- {%if not form.is_hidden %}
+{{wizard.management_form}}
+ {%if not wizard.form.is_hidden %}
<table>
- {{ form.as_table }}
+ {{ wizard.form.as_table }}
</table>
{%endif%}
<p>{%if confirm_end_msg %}{{confirm_end_msg|safe}}{%else%}{% trans "Would you like to save them?" %}{%endif%}</p>
diff --git a/ishtar/templates/default_wizard.html b/ishtar/templates/ishtar/wizard/default_wizard.html
index a71565b6e..1996f4e46 100644
--- a/ishtar/templates/default_wizard.html
+++ b/ishtar/templates/ishtar/wizard/default_wizard.html
@@ -18,19 +18,21 @@
</ul>
<div class='form'>
{% if reminder %}<div class='reminder'>{{ reminder }}</div>{%endif%}
-{% if form.forms %}
+{{ wizard.form.media }}
+{{ wizard.management_form }}
+{% if wizard.form.forms %}
+ {{ wizard.form.management_form }}
<div class='top_button'><input type="submit" id="submit_form" value="{% trans "Validate" %}"/></div>
<table class='formset'>
- {%if form.non_form_errors%}<tr class='error'><th colspan='2'>{{form.non_form_errors}}</th></tr>{%endif%}
- {{ form.management_form }}
- {% for formsetform in form.forms %}
+ {%if wizard.form.non_form_errors%}<tr class='error'><th colspan='2'>{{wizard.form.non_form_errors}}</th></tr>{%endif%}
+ {% for formsetform in wizard.form.forms %}
{% table_form formsetform %}
{% endfor %}
<tr class='modify'><td colspan="2"><button name="formset_modify" value="{{form_step}}">{% trans "Add/Modify" %}</button></td></tr></li>
</table>
{% else %}
<table>
-{% table_form form %}
+{% table_form wizard.form %}
</table>
{% endif %}
<input type="hidden" name="{{ step_field }}" value="{{ step0 }}" />
diff --git a/ishtar/urls.py b/ishtar/urls.py
index baa906979..2723eb1cf 100644
--- a/ishtar/urls.py
+++ b/ishtar/urls.py
@@ -3,7 +3,7 @@ from django.conf.urls.defaults import *
from django.contrib.auth.models import User
from django.contrib import admin
admin.autodiscover()
-admin.site.unregister(User)
+#admin.site.unregister(User)
from settings import URL_PATH