diff options
Diffstat (limited to 'ishtar_common/views.py')
-rw-r--r-- | ishtar_common/views.py | 730 |
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), |