summaryrefslogtreecommitdiff
path: root/ishtar_common/wizards.py
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2018-04-19 13:38:18 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2018-06-12 08:42:11 +0200
commit56648473d068541fe4e0693ea277ea07527de4e9 (patch)
treec3857756acca92ebb4010a8892c773fa8cc33c19 /ishtar_common/wizards.py
parentdf0907b458d432fcd8d383276881e68f759ddc3c (diff)
downloadIshtar-56648473d068541fe4e0693ea277ea07527de4e9.tar.bz2
Ishtar-56648473d068541fe4e0693ea277ea07527de4e9.zip
Wizard: fix M2M data storage in formset
Diffstat (limited to 'ishtar_common/wizards.py')
-rw-r--r--ishtar_common/wizards.py212
1 files changed, 130 insertions, 82 deletions
diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py
index ca4937ec3..5f3da1130 100644
--- a/ishtar_common/wizards.py
+++ b/ishtar_common/wizards.py
@@ -231,11 +231,14 @@ class Wizard(NamedUrlWizardView):
self.ignore_init_steps]
def get_context_data(self, form, **kwargs):
- """Add previous, next and current steps to manage the wizard path"""
+ """
+ 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_label': self.form_list[current_step].form_label,
'wizard_label': self.get_label(),
'current_object': self.get_current_object(),
@@ -243,9 +246,11 @@ class Wizard(NamedUrlWizardView):
[k for k in self.main_item_select_keys
if current_step.startswith(k)]) if current_step else False
}
+
context.update(dct)
if step == current_step:
return context
+
previous_steps, next_steps, previous_step_counter = [], [], 0
while step:
if step == current_step \
@@ -257,6 +262,7 @@ class Wizard(NamedUrlWizardView):
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
@@ -264,15 +270,20 @@ class Wizard(NamedUrlWizardView):
# if self.modification or True:
next_step = self.steps.first
current_step_passed, no_next = False, False
+
# force rechecking of conditions
self.get_form_list()
last_step_is_available = True
+
while next_step:
+
# check if the form is initialized otherwise initialize it
+ # put initialized data in session
if self.modification and not storage.get_step_data(next_step):
values = self.get_form_initial(next_step)
prefixed_values = MultiValueDict()
if not isinstance(values, list):
+ # simple form
for key in values:
form_key = next_step + '-' + key
if isinstance(values, MultiValueDict):
@@ -281,11 +292,17 @@ class Wizard(NamedUrlWizardView):
else:
prefixed_values[form_key] = values[key]
else:
+ # formset
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]
+ if isinstance(v, MultiValueDict):
+ prefixed_values.setlist(form_key,
+ v.getlist(key))
+ else:
+ prefixed_values[form_key] = v[key]
+
if not prefixed_values and \
next_step not in self.get_ignore_init_steps():
# simulate a non empty data for form that might be
@@ -293,6 +310,7 @@ class Wizard(NamedUrlWizardView):
prefixed_values['__non_empty_data'] = ''
self.prepare_serialization(prefixed_values)
storage.set_step_data(next_step, prefixed_values)
+
if step == next_step:
current_step_passed = True
elif current_step_passed:
@@ -1101,6 +1119,7 @@ class Wizard(NamedUrlWizardView):
current_obj = self.get_current_object()
current_step = self.steps.current
request = self.request
+
step_is_main_select = bool([k for k in self.main_item_select_keys
if step.startswith(k)])
if step_is_main_select and step in self.form_list \
@@ -1114,6 +1133,7 @@ class Wizard(NamedUrlWizardView):
return MultiValueDict({'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 = MultiValueDict()
@@ -1135,96 +1155,125 @@ class Wizard(NamedUrlWizardView):
obj_name = prefixes[-2]
return obj_name
+ def _get_instanced_init_for_form(self, obj, c_form):
+ """
+ Get initial data from an object: simple form
+ """
+ initial = MultiValueDict()
+ for base_field in c_form.base_fields.keys():
+ value = obj
+ base_model = None
+ if hasattr(c_form, 'base_model') and \
+ base_field == c_form.base_model:
+ base_model = base_field
+ if hasattr(c_form, 'base_models') and \
+ base_field in c_form.base_models:
+ base_model = base_field
+ if base_model:
+ key = base_model + 's'
+ initial.setlist(base_field, [
+ unicode(val.pk) for val in getattr(value, key).all()])
+ else:
+ fields = base_field.split('__')
+ for field in fields:
+ if callable(value):
+ value = value()
+ if not hasattr(value, field) or \
+ getattr(value, field) is None:
+ value = obj
+ break
+ value = getattr(value, field)
+ if hasattr(value, 'all') and callable(value.all):
+ if not value.count():
+ continue
+ initial.setlist(base_field,
+ [unicode(v.pk) for v in value.all()])
+ continue
+ if value == obj:
+ continue
+ if hasattr(value, 'pk'):
+ value = value.pk
+ if value in (True, False) \
+ or isinstance(value, ImageFieldFile) \
+ or isinstance(value, FileField):
+ initial[base_field] = value
+ elif value is not None:
+ initial[base_field] = unicode(value)
+ return initial
+
+ def _get_instanced_init_for_formset(self, obj, current_step, c_form):
+ """
+ Get initial data from an object: formset
+ """
+ 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()
+ 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:
+ break
+ vals = MultiValueDict()
+ 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 is not None:
+ vals[field] = unicode(value)
+ elif hasattr(child_obj, field + "s"):
+ # M2M
+ vals.setlist(field, [
+ unicode(v.pk)
+ for v in getattr(child_obj, field + "s").all()
+ ])
+ if vals:
+ initial.append(vals)
+ return initial
+
def get_instanced_init(self, obj, step=None):
- """Get initial data from an init"""
+ """
+ Get initial data from an object
+ """
current_step = step or self.steps.current
c_form = self.form_list[current_step]
+
# make the current object the default item for the session
self.request.session[self.get_object_name(obj)] = unicode(obj.pk)
+
initial = MultiValueDict()
+ # posted data or already in session
if self.request.POST or \
(step in self.request.session[self.storage.prefix] and
self.request.session[self.storage.prefix]['step_data'][step]):
return initial
+
if hasattr(c_form, 'base_fields'):
- for base_field in c_form.base_fields.keys():
- value = obj
- base_model = None
- if hasattr(c_form, 'base_model') and \
- base_field == c_form.base_model:
- base_model = base_field
- if hasattr(c_form, 'base_models') and \
- base_field in c_form.base_models:
- base_model = base_field
- if base_model:
- key = base_model + 's'
- initial.setlist(base_field, [
- unicode(val.pk) for val in getattr(value, key).all()])
- else:
- fields = base_field.split('__')
- for field in fields:
- if callable(value):
- value = value()
- if not hasattr(value, field) or \
- getattr(value, field) is None:
- value = obj
- break
- value = getattr(value, field)
- if hasattr(value, 'all') and callable(value.all):
- if not value.count():
- continue
- initial.setlist(base_field,
- [unicode(v.pk) for v in value.all()])
- continue
- if value == obj:
- continue
- if hasattr(value, 'pk'):
- value = value.pk
- if value in (True, False) \
- or isinstance(value, ImageFieldFile) \
- or isinstance(value, FileField):
- initial[base_field] = value
- elif value is not None:
- initial[base_field] = unicode(value)
+ return self._get_instanced_init_for_form(obj, c_form)
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()
- 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:
- 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 is not None:
- vals[field] = unicode(value)
- if vals:
- initial.append(vals)
+ return self._get_instanced_init_for_formset(obj, current_step,
+ c_form)
return initial
@@ -1418,6 +1467,7 @@ class AccountWizard(Wizard):
model = models.Person
formset_pop_deleted = False
wizard_done_window = reverse_lazy('show-person')
+ modification = True
def get_formated_datas(self, forms):
datas = super(AccountWizard, self).get_formated_datas(forms)
@@ -1482,7 +1532,6 @@ class AccountWizard(Wizard):
profile_form = form_dict['profile-account_management']
for form in profile_form:
data = form.cleaned_data
- print(data)
profile = None
if data.get('pk', None):
try:
@@ -1522,7 +1571,6 @@ class AccountWizard(Wizard):
for area in areas:
profile.areas.add(area)
-
final_form = form_dict['final-account_management']
if settings.ADMINS and type(final_form.cleaned_data) == dict and \
final_form.cleaned_data.get('send_password', None):