summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2026-02-04 15:13:56 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2026-02-04 16:54:00 +0100
commit48f9e3d7b4d325e454ea8b0cb51a074dd6ba6fe0 (patch)
tree1032be5dca7239c2decede5397dd8cebf2867096
parentceb2af2f33d6d8c120bbd8e140821b0a1c671113 (diff)
downloadIshtar-48f9e3d7b4d325e454ea8b0cb51a074dd6ba6fe0.tar.bz2
Ishtar-48f9e3d7b4d325e454ea8b0cb51a074dd6ba6fe0.zip
🐛 JSON fields - base finds: manage base finds JSON fields in edit forms
-rw-r--r--ishtar_common/forms.py7
-rw-r--r--ishtar_common/models.py43
-rw-r--r--ishtar_common/wizards.py155
3 files changed, 119 insertions, 86 deletions
diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py
index 899cdc6d1..9558186bb 100644
--- a/ishtar_common/forms.py
+++ b/ishtar_common/forms.py
@@ -368,9 +368,14 @@ class CustomForm(BSForm):
"json_field__key",
"json_field__value_type",
"json_field__name",
+ "json_field__content_type__model",
).order_by("order")
for field in q.all():
- key = "data__" + field["json_field__key"]
+ key = "data__"
+ # base find used in find form -> clearly identify them
+ if field["json_field__content_type__model"] == "basefind":
+ key = "get_first_base_find__" + key
+ key += field["json_field__key"]
field_cls, widget = forms.CharField, None
if field["json_field__value_type"] in JSON_VALUE_TYPES_FIELDS:
field_cls, widget = JSON_VALUE_TYPES_FIELDS[
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 2a8e9fdad..5e8107d17 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -1781,23 +1781,24 @@ class CustomForm(models.Model):
ADMIN_SECTION = _("Custom data / custom forms")
MODELS = {
- "contextrecord": ("archaeological_context_records", "contextrecord"),
- "file": ("archaeological_files", "contextrecord"),
- "adminact": ("archaeological_operations", "administrativeact"),
- "operation": ("archaeological_operations", "operation"),
- "archaeological_site": ("archaeological_operations", "archaeologicalsite"),
- "find": ("archaeological_finds", "find"),
- "findbasket": ("archaeological_finds", "findbasket"),
- "treatment": ("archaeological_finds", "treatment"),
- "treatmentfile": ("archaeological_finds", "treatmentfile"),
- "exhibition": ("archaeological_finds", "exhibition"),
- "warehouse": ("archaeological_warehouse", "warehouse"),
- "container": ("archaeological_warehouse", "container"),
- "person": ("ishtar_common", "person"),
- "organization": ("ishtar_common", "organization"),
- "biographicalnote": ("ishtar_common", "biographicalnote"),
- "document": ("ishtar_common", "document"),
- "geoitem": ("ishtar_common", "geovectordata"),
+ "contextrecord": (("archaeological_context_records", "contextrecord"),),
+ "file": (("archaeological_files", "contextrecord"),),
+ "adminact": (("archaeological_operations", "administrativeact"),),
+ "operation": (("archaeological_operations", "operation"),),
+ "archaeological_site": (("archaeological_operations", "archaeologicalsite"),),
+ "find": (("archaeological_finds", "find"),
+ ("archaeological_finds", "basefind")),
+ "findbasket": (("archaeological_finds", "findbasket"),),
+ "treatment": (("archaeological_finds", "treatment"),),
+ "treatmentfile": (("archaeological_finds", "treatmentfile"),),
+ "exhibition": (("archaeological_finds", "exhibition"),),
+ "warehouse": (("archaeological_warehouse", "warehouse"),),
+ "container": (("archaeological_warehouse", "container"),),
+ "person": (("ishtar_common", "person"),),
+ "organization": (("ishtar_common", "organization"),),
+ "biographicalnote": (("ishtar_common", "biographicalnote"),),
+ "document": (("ishtar_common", "document"),),
+ "geoitem": (("ishtar_common", "geovectordata"),),
}
def natural_key(self):
@@ -1870,10 +1871,10 @@ class CustomForm(models.Model):
model_name = self.form.split("-")[0]
content_types = []
if model_name in self.MODELS:
- app_name, model_name = self.MODELS[model_name]
- q = ContentType.objects.filter(app_label=app_name, model=model_name)
- if q.count():
- content_types.append(q.all()[0])
+ for app_name, model_name in self.MODELS[model_name]:
+ q = ContentType.objects.filter(app_label=app_name, model=model_name)
+ if q.count():
+ content_types.append(q.all()[0])
if not content_types:
register, register_fields = self.register()
if self.form not in self._register:
diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py
index 4fb1222c3..5e23d469a 100644
--- a/ishtar_common/wizards.py
+++ b/ishtar_common/wizards.py
@@ -687,19 +687,29 @@ class Wizard(IshtarWizard):
dct = self.get_extra_model(dct, m2m, form_list)
obj = self.get_current_saved_object()
data = {}
+ base_find_data = {}
if obj and hasattr(obj, "data"):
data = obj.data
-
+ if obj and hasattr(obj, "get_first_base_find"):
+ bf = obj.get_first_base_find()
+ if bf:
+ base_find_data = bf.data
# manage dependant items and json fields
other_objs = {}
for k in list(dct.keys()):
if "__" not in k:
continue
+ vals = k.split("__")
# manage json field
- if k.startswith("data__"):
- data_keys = k[len("data__") :].split("__")
+ if "data" in vals:
+ data_keys = vals[vals.index("data") + 1:]
# tree
- current_data = data
+ if vals[0] == "get_first_base_find":
+ if "get_first_base_find" not in other_objs:
+ other_objs["get_first_base_find"] = {}
+ current_data = base_find_data
+ else:
+ current_data = data
for data_key in data_keys[:-1]:
if data_key not in current_data:
current_data[data_key] = {}
@@ -714,13 +724,14 @@ class Wizard(IshtarWizard):
current_data[data_keys[-1]] = value
continue
- vals = k.split("__")
if len(vals) != 2:
raise NotImplementedError("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 "get_first_base_find" in other_objs and base_find_data:
+ other_objs["get_first_base_find"]["data"] = base_find_data
if obj:
for k in list(dct.keys()):
if k.startswith("pk"):
@@ -1517,6 +1528,78 @@ class Wizard(IshtarWizard):
obj_name = prefixes[-2]
return obj_name
+ def __instanced_json_data(self, initial, c_form, obj):
+ """
+ Get initial data for JSON fields
+ """
+ for key in self.json_fields[c_form.form_slug]:
+ data_key = "data__"
+ current_obj = obj
+ if not key.startswith("data__"):
+ if not key.startswith("get_first_base_find__data__") \
+ or not hasattr(obj, "get_first_base_find"):
+ continue
+ data_key = "get_first_base_find__data__"
+ current_obj = obj.get_first_base_find()
+ if not current_obj:
+ continue
+ json_keys = key[len(data_key):].split("__")
+ value = current_obj.data
+ for json_key in json_keys:
+ if json_key not in value:
+ value = None
+ break
+ value = value[json_key]
+ if value:
+ initial[key] = value
+ elif value is False:
+ initial[key] = "False"
+
+ def __instanced_data(self, initial, c_form, obj, base_field):
+ """
+ Get initial data for standard fields
+ """
+ value = obj
+ base_model = None
+ if (hasattr(c_form, "base_model") and base_field == c_form.base_model) or (
+ hasattr(c_form, "base_models") and base_field in c_form.base_models):
+ base_model = base_field
+ try:
+ getattr(obj, base_model + "s")
+ key = base_model + "s"
+ except AttributeError:
+ getattr(obj, base_model)
+ key = base_model
+ initial.setlist(
+ base_field, [str(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():
+ return
+ initial.setlist(base_field, [str(v.pk) for v in value.all()])
+ return
+ if value == obj:
+ return
+ 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] = str(value)
+
def _get_instanced_init_for_form(self, obj, c_form):
"""
Get initial data from an object: simple form
@@ -1525,71 +1608,15 @@ class Wizard(IshtarWizard):
# manage json field
if (
- hasattr(obj, "data")
- and obj.data
+ getattr(obj, "data", None)
and hasattr(self, "json_fields")
and getattr(c_form, "form_slug", None)
and c_form.form_slug in self.json_fields
- and obj.data
):
- for key in self.json_fields[c_form.form_slug]:
- if not key.startswith("data__"):
- continue
- json_keys = key[len("data__") :].split("__")
- value = obj.data
- for json_key in json_keys:
- if json_key not in value:
- value = None
- break
- value = value[json_key]
- if value:
- initial[key] = value
- elif value is False:
- initial[key] = "False"
+ self.__instanced_json_data(initial, c_form, obj)
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:
- try:
- __ = getattr(obj, base_model + "s")
- key = base_model + "s"
- except AttributeError:
- __ = getattr(obj, base_model)
- key = base_model
- initial.setlist(
- base_field, [str(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, [str(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] = str(value)
+ self.__instanced_data(initial, c_form, obj, base_field)
return initial
@staticmethod