summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2026-04-01 12:37:31 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2026-04-01 16:10:17 +0200
commit136986832aee92b839c0628f7e5bbde22fe7d264 (patch)
treea31380e61e2c62282bda56fe9a205af3177407c6
parente8435aa231663776590d12b0517a08892dfd8f86 (diff)
downloadIshtar-136986832aee92b839c0628f7e5bbde22fe7d264.tar.bz2
Ishtar-136986832aee92b839c0628f7e5bbde22fe7d264.zip
✨ general management of filter on types - filter qualification types for actors
-rw-r--r--archaeological_finds/models_finds.py2
-rw-r--r--archaeological_operations/forms.py2
-rw-r--r--ishtar_common/forms.py17
-rw-r--r--ishtar_common/models.py5
-rw-r--r--ishtar_common/models_common.py20
-rw-r--r--ishtar_common/widgets.py14
6 files changed, 46 insertions, 14 deletions
diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py
index 9b4156a9d..b57002532 100644
--- a/archaeological_finds/models_finds.py
+++ b/archaeological_finds/models_finds.py
@@ -207,6 +207,7 @@ class TreatmentType(HierarchicalType):
initial=None,
force=False,
full_hierarchy=False,
+ limit=None
):
types = super(TreatmentType, cls).get_types(
dct=dct,
@@ -217,6 +218,7 @@ class TreatmentType(HierarchicalType):
initial=initial,
force=force,
full_hierarchy=full_hierarchy,
+ limit=limit
)
if dct and not exclude:
rank = 0
diff --git a/archaeological_operations/forms.py b/archaeological_operations/forms.py
index 82f41c089..a96ce7c63 100644
--- a/archaeological_operations/forms.py
+++ b/archaeological_operations/forms.py
@@ -1343,7 +1343,7 @@ class SiteForm(CustomForm, ManageOldType):
required=False)
actor = widgets.Select2MultipleField(
model=QualifiedBiographicalNote, label=_("Actors"), required=False,
- remote=True, new=True)
+ remote=True, new=True, remote_filter='qualification_type__S-A')
collaborator = widgets.Select2MultipleField(
model=Person, label=_("Collaborators"), required=False,
remote=True, new=True)
diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py
index 4db6a138b..416a1a9ec 100644
--- a/ishtar_common/forms.py
+++ b/ishtar_common/forms.py
@@ -707,8 +707,8 @@ class FieldType:
self.empty_first = empty_first
self.help_text = help_text
- def get_choices(self, initial=None):
- args = {"empty_first": self.empty_first, "initial": initial}
+ def get_choices(self, initial=None, limit=None):
+ args = {"empty_first": self.empty_first, "initial": initial, "limit": limit}
if self.extra_args:
args.update(self.extra_args)
return self.model.get_types(**args)
@@ -848,10 +848,14 @@ class IshtarForm(BSForm, forms.Form):
for field in type_lst:
self._init_type(field)
- def _init_type(self, field):
+ def _init_type(self, field, extra=None):
if field.key not in self.fields:
return
- self.fields[field.key].choices = field.get_choices()
+ if not extra:
+ extra = {}
+ if hasattr(self, "limits") and field.key in self.limits:
+ extra["limit"] = self.limits[field.key]
+ self.fields[field.key].choices = field.get_choices(**extra)
if not getattr(field, "help_text", True):
return
self.fields[field.key].help_text = field.get_help()
@@ -1349,10 +1353,7 @@ class ManageOldType(IshtarForm):
if field.key not in self.fields:
return
initial = self.init_data.getlist(field.key)
- self.fields[field.key].choices = field.get_choices(
- initial=initial
- )
- self.fields[field.key].help_text = field.get_help()
+ super()._init_type(field, extra={"initial": initial})
class QAForm(CustomForm, ManageOldType):
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index e52d210a6..d9923b04d 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -4702,6 +4702,10 @@ class QualifiedBiographicalNoteType(OrderedHierarchicalType):
ordering = ["order", "label"]
ADMIN_SECTION = _("Directory")
+ @classmethod
+ def _set_limit(cls, dct, limit):
+ dct["model__in"] = limit
+
post_save.connect(post_save_cache, sender=QualifiedBiographicalNoteType)
post_delete.connect(post_save_cache, sender=QualifiedBiographicalNoteType)
@@ -6200,6 +6204,7 @@ class OperationType(GeneralType):
empty_first=True,
default=None,
initial=None,
+ limit=None
):
dct = dct or {}
exclude = exclude or []
diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py
index ba27b3bbc..117981e79 100644
--- a/ishtar_common/models_common.py
+++ b/ishtar_common/models_common.py
@@ -403,6 +403,7 @@ class GeneralType(Cached, models.Model):
initial=None,
force=False,
full_hierarchy=False,
+ limit=None
):
if not dct:
dct = {}
@@ -412,7 +413,8 @@ class GeneralType(Cached, models.Model):
if not instances and empty_first and not default:
types = [("", "--")]
types += cls._pre_get_types(
- dct, instances, exclude, default, force, get_full_hierarchy=full_hierarchy
+ dct, instances, exclude, default, force, get_full_hierarchy=full_hierarchy,
+ limit=limit
)
if not initial:
return types
@@ -421,6 +423,13 @@ class GeneralType(Cached, models.Model):
return types
@classmethod
+ def _set_limit(cls, dct, limit):
+ """
+ Translate limit set in forms to a query filter
+ """
+ raise NotImplementedError(f"_set_limit method must be set for {cls}")
+
+ @classmethod
def _pre_get_types(
cls,
dct=None,
@@ -429,6 +438,7 @@ class GeneralType(Cached, models.Model):
default=None,
force=False,
get_full_hierarchy=False,
+ limit=None
):
if not dct:
dct = {}
@@ -439,11 +449,15 @@ class GeneralType(Cached, models.Model):
if not instances:
keys = ["__get_types"]
keys += ["{}".format(ex) for ex in exclude] + ["{}".format(default)]
+ if limit:
+ keys.append("lim" + ";".join(limit))
keys += ["{}-{}".format(str(k), dct[k]) for k in dct]
cache_key, value = get_cache(cls, keys)
if value and not force:
return value
base_dct = dct.copy()
+ if limit:
+ cls._set_limit(base_dct, limit)
if hasattr(cls, "parent"):
if not cache_key:
return cls._get_parent_types(
@@ -467,7 +481,9 @@ class GeneralType(Cached, models.Model):
return vals
if not cache_key:
- return cls._get_types(base_dct, instances, exclude=exclude, default=default)
+ return cls._get_types(
+ base_dct, instances, exclude=exclude, default=default
+ )
vals = [
v
for v in cls._get_types(
diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py
index b11ae0c5d..304e6a669 100644
--- a/ishtar_common/widgets.py
+++ b/ishtar_common/widgets.py
@@ -232,12 +232,16 @@ class Select2DynamicMultipleField(forms.MultipleChoiceField):
class Select2Base(Select2Media):
def __init__(
- self, attrs=None, choices=(), remote=None, model=None, new=None, available=None
+ self, attrs=None, choices=(), remote=None, model=None, new=None, available=None,
+ remote_filter=None
):
self.remote = remote
self.available = available
self.model = model
self.new = new
+ self.remote_filter = None
+ if attrs and "remote_filter" in attrs:
+ self.remote_filter = attrs.pop("remote_filter")
super(Select2Base, self).__init__(attrs, choices)
def get_q(self):
@@ -275,8 +279,8 @@ class Select2Base(Select2Media):
attrs["style"] = "width: 370px"
if value and getattr(self, "multiple", False) and \
- not isinstance(value, (list, tuple)):
- value = value.split(",")
+ not isinstance(value, (list, tuple)):
+ value = value.split(",")
options = ""
if self.remote:
@@ -331,6 +335,8 @@ class Select2Base(Select2Media):
html = "<div class='input-group'>"
url_new = "new-" + self.model.SLUG
url_new = reverse(url_new, args=["id_" + name])
+ if self.remote_filter:
+ url_new += self.remote_filter
# WARNING: the modal for the form must be in the main template
# "extra_form_modals" list is used for that in form or view
new = (
@@ -412,6 +418,8 @@ class Select2BaseField(object):
attrs["modal"] = kwargs.pop("modal")
if kwargs.get("style", None):
attrs["style"] = kwargs.pop("style")
+ if kwargs.get("remote_filter", None):
+ attrs["remote_filter"] = kwargs.pop("remote_filter")
kwargs["widget"] = widget(
model=self.model,
available=self.available,