diff options
Diffstat (limited to 'ishtar_common/wizards.py')
-rw-r--r-- | ishtar_common/wizards.py | 86 |
1 files changed, 74 insertions, 12 deletions
diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py index c065459f6..4f0295421 100644 --- a/ishtar_common/wizards.py +++ b/ishtar_common/wizards.py @@ -18,6 +18,7 @@ # See the file COPYING for details. import datetime +import logging # from functools import wraps from django.conf import settings @@ -38,6 +39,8 @@ from django.utils.datastructures import MultiValueDict as BaseMultiValueDict from django.utils.translation import ugettext_lazy as _ import models +logger = logging.getLogger(__name__) + class MultiValueDict(BaseMultiValueDict): def get(self, *args, **kwargs): @@ -124,8 +127,12 @@ class Wizard(NamedUrlWizardView): wizard_templates = {} filter_owns = {} current_obj_slug = '' + current_object_key = 'pk' + ignore_init_steps = [] file_storage = default_storage + saved_args = {} # argument to pass on object save + ''' # buggy and unecessary... def __init__(self, *args, **kwargs): @@ -165,6 +172,13 @@ class Wizard(NamedUrlWizardView): return super(Wizard, self).dispatch(request, *args, **kwargs) + def get_form_kwargs(self, step=None): + kwargs = super(Wizard, self).get_form_kwargs(step) + if hasattr(self.form_list[step], 'need_user_for_initialization') and\ + self.form_list[step].need_user_for_initialization: + kwargs['user'] = self.request.user + return kwargs + def get_prefix(self, *args, **kwargs): """As the class name can interfere when reused prefix with the url_name """ @@ -188,13 +202,17 @@ class Wizard(NamedUrlWizardView): templates = [self.wizard_confirm] + templates return templates + def get_ignore_init_steps(self): + return ['{}-{}'.format(step, self.url_name) for step in + self.ignore_init_steps] + 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) self.request.session['CURRENT_ACTION'] = self.get_wizard_name() step = self.steps.first current_step = self.steps.current - dct = {'current_step': self.form_list[current_step], + dct = {'current_step_label': self.form_list[current_step].form_label, 'wizard_label': self.label, 'current_object': self.get_current_object(), 'is_search': current_step.startswith('selec-') @@ -209,7 +227,7 @@ class Wizard(NamedUrlWizardView): or (previous_steps and previous_steps[-1] == self.form_list[step]): break - previous_steps.append(self.form_list[step]) + previous_steps.append(self.form_list[step].form_label) previous_step_counter += 1 if previous_step_counter >= len(self.steps): break @@ -242,7 +260,8 @@ class Wizard(NamedUrlWizardView): for key in v: form_key = next_step + prefix + key prefixed_values[form_key] = v[key] - if not prefixed_values: + if not prefixed_values and \ + next_step not in self.get_ignore_init_steps(): # simulate a non empty data for form that might be # valid when empty prefixed_values['__non_empty_data'] = '' @@ -250,7 +269,7 @@ class Wizard(NamedUrlWizardView): if step == next_step: current_step_passed = True elif current_step_passed: - next_steps.append(self.form_list[next_step]) + next_steps.append(self.form_list[next_step].form_label) next_step = self.get_next_step(next_step) context.update({'next_steps': next_steps}) # not last step: validation @@ -469,6 +488,8 @@ class Wizard(NamedUrlWizardView): for k in dct: if k.startswith('pk'): continue + if k not in obj.__class__._meta.get_all_field_names(): + continue # False set to None for images and files if not k.endswith('_id') and ( isinstance(obj.__class__._meta.get_field(k), FileField) or @@ -483,9 +504,12 @@ class Wizard(NamedUrlWizardView): elif type(dct[k]) not in (list, tuple): dct[k] = [dct[k]] setattr(obj, k, dct[k]) + if hasattr(obj, 'pre_save'): + obj.pre_save() try: obj.full_clean() - except ValidationError: + except ValidationError as e: + logger.warning(unicode(e)) return self.render(form_list[-1]) for dependant_item in other_objs: c_item = getattr(obj, dependant_item) @@ -543,12 +567,25 @@ class Wizard(NamedUrlWizardView): dct[dependant_item] = c_item if 'pk' in dct: dct.pop('pk') + # remove non relevant fields + all_field_names = self.get_saved_model()._meta.get_all_field_names() + for k in dct.copy(): + if (k.endswith('_id') and k[:-3] not in all_field_names) and \ + k not in all_field_names: + dct.pop(k) + saved_args = self.saved_args.copy() + for k in saved_args: + if k in dct: + saved_args[k] = dct.pop(k) obj = self.get_saved_model()(**dct) + if hasattr(obj, 'pre_save'): + obj.pre_save() try: obj.full_clean() - except ValidationError: + except ValidationError as e: + logger.warning(unicode(e)) return self.render(form_list[-1]) - obj.save() + obj.save(**saved_args) for k in adds: getattr(obj, k).add(adds[k]) # necessary to manage interaction between models like @@ -561,6 +598,12 @@ class Wizard(NamedUrlWizardView): old_m2ms = {} for model in whole_associated_models: related_model = getattr(obj, model + 's') + # manage through + if hasattr(related_model, 'through') and related_model.through: + related_set_name = str( + related_model.through.__name__ + '_set').lower() + if hasattr(obj, related_set_name): + related_model = getattr(obj, related_set_name) # clear real m2m if hasattr(related_model, 'clear'): old_m2ms[model] = [] @@ -587,6 +630,9 @@ class Wizard(NamedUrlWizardView): if value not in m2m_items[key]: if type(value) == dict: model = related_model.model + if hasattr(related_model, 'through') and \ + related_model.through: + model = related_model.through # not m2m -> foreign key if not hasattr(related_model, 'clear'): assert hasattr(model, 'MAIN_ATTR'), \ @@ -611,8 +657,13 @@ class Wizard(NamedUrlWizardView): else: if issubclass(model, models.BaseHistorizedItem): value['history_modifier'] = self.request.user - value = model.objects.create(**value) - value.save() + if hasattr(model, 'RELATIVE_MODELS') and \ + self.get_saved_model() in \ + model.RELATIVE_MODELS: + value[model.RELATIVE_MODELS[ + self.get_saved_model()]] = obj + value, created = model.objects.get_or_create(**value) + value.save() # force post_save # check that an item is not add multiple times (forged forms) if value not in related_model.all() and\ hasattr(related_model, 'add'): @@ -626,6 +677,7 @@ class Wizard(NamedUrlWizardView): self.request.session[self.current_obj_slug] = unicode(obj.pk) self.request.session[self.get_object_name(obj)] = unicode(obj.pk) dct = {'item': obj} + self.current_object = obj # force evaluation of lazy urls wizard_done_window = unicode(self.wizard_done_window) if wizard_done_window: @@ -877,7 +929,7 @@ class Wizard(NamedUrlWizardView): current_obj = None main_form_key = 'selec-' + self.url_name try: - idx = self.session_get_value(main_form_key, 'pk') + idx = self.session_get_value(main_form_key, self.current_object_key) idx = int(idx) current_obj = self.model.objects.get(pk=idx) except(TypeError, ValueError, ObjectDoesNotExist): @@ -980,8 +1032,18 @@ class Wizard(NamedUrlWizardView): if not hasattr(obj, key): return initial keys = c_form.form.base_fields.keys() - query = getattr(obj, key) - if not obj._meta.ordering: + related = getattr(obj, key) + # manage through + through = False + if hasattr(related, 'through') and related.through: + related_set_name = str( + related.through.__name__ + '_set').lower() + if hasattr(obj, related_set_name): + through = True + related = getattr(obj, related_set_name) + + query = related + if not through and not obj._meta.ordering: query = query.order_by('pk') for child_obj in query.all(): if not keys: |