summaryrefslogtreecommitdiff
path: root/ishtar_common/wizards.py
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common/wizards.py')
-rw-r--r--ishtar_common/wizards.py86
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: