summaryrefslogtreecommitdiff
path: root/ishtar_common/wizards.py
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2018-04-24 12:44:18 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2018-06-12 08:43:58 +0200
commitd083ce1b75dc70f1c69b5207e2606d33b1b0e9a3 (patch)
tree17c2e17a835bde449b988b8725170e65f1ff235e /ishtar_common/wizards.py
parent458174b3dc14a3a1bc8cc4f3bb10fccdd8dc824a (diff)
downloadIshtar-d083ce1b75dc70f1c69b5207e2606d33b1b0e9a3.tar.bz2
Ishtar-d083ce1b75dc70f1c69b5207e2606d33b1b0e9a3.zip
Wizards: manage intermediary model for M2M relations
Diffstat (limited to 'ishtar_common/wizards.py')
-rw-r--r--ishtar_common/wizards.py50
1 files changed, 43 insertions, 7 deletions
diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py
index e47d5b48b..70f3caa19 100644
--- a/ishtar_common/wizards.py
+++ b/ishtar_common/wizards.py
@@ -525,7 +525,7 @@ class Wizard(NamedUrlWizardView):
frm.cleaned_data.pop('DELETE')
for key in frm.cleaned_data:
value = frm.cleaned_data[key]
- if value is None or value == '':
+ if value is None or value in ['', []]:
continue
if key in associated_models:
value = associated_models[key].objects.get(
@@ -736,6 +736,18 @@ class Wizard(NamedUrlWizardView):
r.delete()
for key, value in m2m:
related_model = getattr(obj, key + 's')
+ related_data = {} # used for intermediary models
+
+ # an intermediary model is used
+ if not related_model.through._meta.auto_created:
+ for field in related_model.through._meta.get_fields():
+ # is used for the obj or target
+ if getattr(field, 'related_model', None) and \
+ (field.related_model == related_model.model or
+ isinstance(obj, field.related_model)):
+ continue
+ related_data[field.name] = None
+
if key not in m2m_items:
if type(key) == dict:
vals = []
@@ -747,6 +759,7 @@ class Wizard(NamedUrlWizardView):
m2m_items[key] = vals
else:
m2m_items[key] = related_model.all()
+
if value not in m2m_items[key]:
if type(value) == dict:
model = related_model.model
@@ -794,8 +807,7 @@ class Wizard(NamedUrlWizardView):
# should be managed normally in forms but...
fields = model._meta.get_fields()
-
- has_problemetic_null = False
+ has_problematic_null = False
for field in fields:
if (field.name not in value
or not value[field.name]) \
@@ -806,14 +818,19 @@ class Wizard(NamedUrlWizardView):
and (hasattr(field, 'default')
and (not field.default
or field.default == NOT_PROVIDED)):
- has_problemetic_null = True
+ has_problematic_null = True
break
- if has_problemetic_null:
+ if has_problematic_null:
continue
if hasattr(model, 'data') and 'data' not in value:
value['data'] = {}
+ # remove intermediary model keys
+ for k in related_data.keys():
+ if k in value:
+ related_data[k] = value.pop(k)
+
if get_or_create:
value, created = model.objects.get_or_create(
**value)
@@ -821,11 +838,30 @@ class Wizard(NamedUrlWizardView):
value = model.objects.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\
+ if value not in related_model.all() and \
(not hasattr(related_model, 'through') or
not isinstance(value, related_model.through)):
# many to many and the value have been already managed
- related_model.add(value)
+
+ # an intermediary model is used
+ if not related_model.through._meta.auto_created:
+ for field in related_model.through._meta.get_fields():
+ if hasattr(field, 'related_model') \
+ and field.related_model:
+ # assume that one foreign key is used for obj
+ # table and value table - more complex schema
+ # are not managed
+ if isinstance(value,
+ field.related_model):
+ related_data[field.name] = value
+ elif isinstance(obj,
+ field.related_model):
+ related_data[field.name] = obj
+ related_model.through.objects.create(
+ **related_data
+ )
+ else:
+ related_model.add(value)
# necessary to manage interaction between models like
# material_index management for baseitems
obj._cached_label_checked = False