summaryrefslogtreecommitdiff
path: root/ishtar_common/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common/views.py')
-rw-r--r--ishtar_common/views.py730
1 files changed, 1 insertions, 729 deletions
diff --git a/ishtar_common/views.py b/ishtar_common/views.py
index 69fa8b90b..4f010d866 100644
--- a/ishtar_common/views.py
+++ b/ishtar_common/views.py
@@ -33,7 +33,6 @@ import ho.pisa as pisa
from django.conf import settings
from django.contrib.auth import logout
-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
@@ -55,6 +54,7 @@ import forms_main as ishtar_forms
from ishtar_common.forms import FinalForm
from ishtar_common.forms_common import PersonForm, PersonFormSelection,\
AccountForm, FinalAccountForm
+from ishtar_common.wizards import PersonWizard, PersonModifWizard, AccountWizard
import models
CSV_OPTIONS = {'delimiter':';', 'quotechar':'"', 'quoting':csv.QUOTE_ALL}
@@ -74,657 +74,12 @@ def index(request):
return render_to_response('index.html', dct,
context_instance=RequestContext(request))
-class Wizard(NamedUrlWizardView):
- model = None
- label = ''
- 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
- if not hasattr(self.request.user, 'ishtaruser'):
- 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"""
- print "2"
- 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_prefix(self, *args, **kwargs):
- """As the class name can interfere when reused prefix with the url_name
- """
- print "3"
- return self.url_name + super(Wizard, self).get_prefix(*args,
- **kwargs)
-
- def get_wizard_name(self):
- """As the class name can interfere when reused, use the url_name"""
- print "4"
- return self.url_name
-
- def get_template_names(self):
- print "5"
- 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"""
- print "6"
- context = super(Wizard, self).get_context_data(form)
- self.request.session['CURRENT_ACTION'] = self.get_wizard_name()
- step = self.steps.first
- current_step = self.steps.current
- context.update({'current_step':self.form_list[current_step],
- 'wizard_label':self.label})
- if step == current_step:
- return context
- previous_steps, next_steps, previous_step_counter = [], [], 0
- while step:
- if step == current_step \
- or (previous_steps and
- previous_steps[-1] == self.form_list[step]):
- break
- previous_steps.append(self.form_list[step])
- previous_step_counter += 1
- if previous_step_counter >= len(self.steps):
- break
- step = self.steps.all[previous_step_counter]
- context.update({'previous_steps':previous_steps,
- 'previous_step_counter':previous_step_counter})
- storage = self.storage
- # 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(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(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"""
- print "7"
- 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):
- print "8"
- dct['history_modifier'] = self.request.user
- return dct
-
- def done(self, form_list, return_object=False, **kwargs):
- """Save to the model"""
- print "9"
- 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"""
- print "10"
- return self.model
-
- def get_current_saved_object(self):
- """Permit a distinguo when saved model is not the base selected model"""
- print "11"
- return self.get_current_object()
-
- def save_model(self, dct, m2m, whole_associated_models, form_list,
- return_object):
- print "12"
- 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"""
- print "13"
- 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"""
- print "14"
- 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
- """
- print "15"
- 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"""
- print "16"
- 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
- """
- print "17"
- 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"""
- print "18"
- 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"""
- print "19"
- current_obj = None
- main_form_key = 'selec-' + self.url_name
- try:
- idx = self.session_get_value(self.request, self.storage,
- main_form_key, 'pk')
- if type(idx) in (tuple, list):
- idx = idx[0]
- idx = int(idx)
- current_obj = self.model.objects.get(pk=idx)
- except(TypeError, ValueError, ObjectDoesNotExist):
- pass
- return current_obj
-
- def get_form_initial(self, step):
- print "20"
- current_obj = self.get_current_object()
- current_step = self.steps.current
- request = self.request
- 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)
- self.storage.reset()
- 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"""
- print "21"
- 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)],
label=_(u"Person creation"),
url_name='person_creation')
-class PersonModifWizard(PersonWizard):
- modification = True
-
person_modification_wizard = PersonModifWizard.as_view([
('selec-person_modification', PersonFormSelection),
('identity-person_modification', PersonForm),
@@ -732,89 +87,6 @@ person_modification_wizard = PersonModifWizard.as_view([
label=_(u"Person modification"),
url_name='person_modification')
-class AccountWizard(Wizard):
- model = models.Person
- def get_formated_datas(self, forms):
- datas = super(AccountWizard, self).get_formated_datas(forms)
- for form in forms:
- if not hasattr(form, "cleaned_data"):
- continue
- for key in form.cleaned_data:
- if key == 'hidden_password' and form.cleaned_data[key]:
- datas[-1][1].append((_("New password"), "*"*8))
- return datas
-
- def done(self, form_list, **kwargs):
- """
- Save the account
- """
- dct = {}
- for form in form_list:
- if not form.is_valid():
- return self.render(form)
- associated_models = hasattr(form, 'associated_models') and \
- form.associated_models or {}
- if type(form.cleaned_data) == dict:
- for key in form.cleaned_data:
- if key == 'pk':
- continue
- value = form.cleaned_data[key]
- if key in associated_models and value:
- value = associated_models[key].objects.get(pk=value)
- dct[key] = value
- person = self.get_current_object()
- if not person:
- return self.render(form)
- for key in dct.keys():
- if key.startswith('hidden_password'):
- dct['password'] = dct.pop(key)
- try:
- account = models.IshtarUser.objects.get(person=person)
- account.username = dct['username']
- account.email = dct['email']
- except ObjectDoesNotExist:
- now = datetime.datetime.now()
- account = models.IshtarUser(person=person, username=dct['username'],
- email=dct['email'], first_name=person.surname,
- last_name=person.name, is_staff=False, is_active=True,
- is_superuser=False, last_login=now, date_joined=now)
- if dct['password']:
- account.set_password(dct['password'])
- account.save()
-
- if 'send_password' in dct and dct['send_password'] and \
- settings.ADMINS:
- site = Site.objects.get_current()
-
- app_name = site and ("Ishtar - " + site.name) \
- or "Ishtar"
- context = Context({'login':dct['username'],
- 'password':dct['password'],
- 'app_name':app_name,
- 'site': site and site.domain or ""
- })
- t = loader.get_template('account_activation_email.txt')
- msg = t.render(context)
- subject = _(u"[%(app_name)s] Account creation/modification") % {
- "app_name":app_name}
- send_mail(subject, msg, settings.ADMINS[0][1],
- [dct['email']], fail_silently=True)
- res = render_to_response('wizard_done.html', {},
- context_instance=RequestContext(self.request))
- return res
-
- def get_form(self, step=None, data=None, files=None):
- """
- Display the "Send email" field if necessary
- """
- form = super(AccountWizard, self).get_form(step, data, files)
- if not hasattr(form, 'is_hidden'):
- return form
- if self.session_get_value(self.request, self.storage,
- 'account-account_management', 'hidden_password'):
- form.is_hidden = False
- return form
-
account_management_wizard = AccountWizard.as_view([
('selec-account_management', PersonFormSelection),
('account-account_management', AccountForm),