summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2025-10-06 20:49:48 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2025-11-29 17:07:10 +0100
commit702d2f5356b35599cffdebd3f53a19c5e7412e82 (patch)
tree44a6e56e8c47047726f05a4bc3bb1ec151a199ec
parent47ae57c37abfed75f93594255b6c617afa011bf5 (diff)
downloadIshtar-702d2f5356b35599cffdebd3f53a19c5e7412e82.tar.bz2
Ishtar-702d2f5356b35599cffdebd3f53a19c5e7412e82.zip
✨ find - statistics: add top container
-rw-r--r--archaeological_finds/models_finds.py3
-rw-r--r--ishtar_common/utils.py10
-rw-r--r--ishtar_common/views_item.py42
3 files changed, 43 insertions, 12 deletions
diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py
index 56232165f..2d96726ea 100644
--- a/archaeological_finds/models_finds.py
+++ b/archaeological_finds/models_finds.py
@@ -1331,7 +1331,8 @@ class Find(
"base_finds__context_record__operation__towns__areas__parent__label",
_("Extended area"),
),
- ("periods__label", _("Chronological period")),
+ ("container__cached_division__splitpart_|_1", _("Top container")),
+ ("datings__period__label", _("Chronological period")),
("material_types__label", _("Material type")),
("object_types__label", _("Object type")),
("recommended_treatments__label", _("Recommended treatments")),
diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py
index bdd7a67e5..90ae08f0b 100644
--- a/ishtar_common/utils.py
+++ b/ishtar_common/utils.py
@@ -66,7 +66,7 @@ from django.core.files import File
from django.core.files.storage import FileSystemStorage
from django.core.validators import EMPTY_VALUES, MaxValueValidator
from django.db import models
-from django.db.models import Q
+from django.db.models import Func, Q
from django.db.models.functions import Length
from django.http import HttpResponseRedirect
from django.urls import re_path, reverse, NoReverseMatch
@@ -199,6 +199,14 @@ class Round(models.Func):
arg_joiner = "::numeric, "
+class SplitPart(Func):
+ """
+ PostgreSQL split part annotation
+ """
+ function = 'split_part'
+ arity = 3
+
+
CSV_OPTIONS = {"delimiter": ",", "quotechar": '"', "quoting": QUOTE_ALL}
diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py
index 62de9b8b4..83c84ae78 100644
--- a/ishtar_common/views_item.py
+++ b/ishtar_common/views_item.py
@@ -46,6 +46,7 @@ from django.db.models import (
ExpressionWrapper,
FloatField,
FileField,
+ Value
)
from django.db.models.functions import ExtractYear
from django.db.utils import ProgrammingError
@@ -82,8 +83,9 @@ from ishtar_common.utils import (
get_current_profile,
HistoryError,
PRIVATE_FIELDS,
- SearchAltName,
Round,
+ SearchAltName,
+ SplitPart,
)
from .menus import Menu
@@ -2102,10 +2104,19 @@ def _get_json_stats(
value_keys = []
for stat in (stats_modality_1, stats_modality_2):
if not stat:
+ value_keys.append(stat)
continue
if stat.endswith("__year"):
q = q.annotate(**{stat: ExtractYear(stat[:-len("__year")])})
+ if "__splitpart_" in stat:
+ st, args = stat.split("__splitpart_")
+ sep, index = args.split("_")
+ index = int(index)
+ stat = f"{st}_modality"
+ q = q.annotate(**{stat: SplitPart(F(st), Value(sep), index)})
value_keys.append(stat)
+ stats_modality_1, stats_modality_2 = value_keys
+ value_keys = [v for v in value_keys if v]
value_keys.append(stats_sum_variable)
q = q.values(*value_keys)
data = []
@@ -2813,6 +2824,26 @@ def get_item(
sub_items = sub_items.filter(base_query)
if exc_query:
sub_items = sub_items.exclude(exc_query)
+ stats_modality_1, stats_modality_2 = None, None
+ if data_type == "json-stats":
+ stats_modality_1 = request_items.get("stats_modality_1", None)
+ stats_modality_2 = request_items.get("stats_modality_2", None)
+ if (
+ not stats_modality_1
+ or stats_modality_1 not in model.STATISTIC_MODALITIES
+ ):
+ stats_modality_1 = model.STATISTIC_MODALITIES[0]
+ if stats_modality_2 not in model.STATISTIC_MODALITIES:
+ stats_modality_2 = None
+ if getattr(model, "STATISTIC_MODALITIES_QUERY", False):
+ if stats_modality_1 in model.STATISTIC_MODALITIES_QUERY and \
+ "query" in model.STATISTIC_MODALITIES_QUERY[stats_modality_1]:
+ sub_items = sub_items.filter(
+ **model.STATISTIC_MODALITIES_QUERY[stats_modality_1]["query"])
+ if stats_modality_2 in model.STATISTIC_MODALITIES_QUERY and \
+ "query" in model.STATISTIC_MODALITIES_QUERY[stats_modality_2]:
+ sub_items = sub_items.filter(
+ **model.STATISTIC_MODALITIES_QUERY[stats_modality_2]["query"])
for extra in extras:
sub_items = sub_items.extra(**extra)
@@ -2860,15 +2891,6 @@ def get_item(
# print(str(items.values("id").query))
if data_type == "json-stats":
- stats_modality_1 = request_items.get("stats_modality_1", None)
- stats_modality_2 = request_items.get("stats_modality_2", None)
- if (
- not stats_modality_1
- or stats_modality_1 not in model.STATISTIC_MODALITIES
- ):
- stats_modality_1 = model.STATISTIC_MODALITIES[0]
- if stats_modality_2 not in model.STATISTIC_MODALITIES:
- stats_modality_2 = None
stats_sum_variable = request_items.get("stats_sum_variable", None)
stats_sum_variable_keys = list(model.STATISTIC_SUM_VARIABLE.keys())
if (