summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2026-05-04 16:14:16 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2026-05-05 10:13:25 +0200
commit364aabd3f1be53e37fa3f13266b159cdf9a5a439 (patch)
treeab21b5e5082b628825a7ce3911b4d527bdc1e29c
parent17374a9a648e2c5de5526225c3c5bdbc06af9ad3 (diff)
downloadIshtar-364aabd3f1be53e37fa3f13266b159cdf9a5a439.tar.bz2
Ishtar-364aabd3f1be53e37fa3f13266b159cdf9a5a439.zip
🐛 criteria search: fix search with precise and open term for the same criteria
-rw-r--r--archaeological_operations/tests.py7
-rw-r--r--ishtar_common/views_item.py67
2 files changed, 54 insertions, 20 deletions
diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py
index 953229dbc..dc98ba25e 100644
--- a/archaeological_operations/tests.py
+++ b/archaeological_operations/tests.py
@@ -3177,7 +3177,7 @@ class OperationSearchTest(TestCase, OperationInitTest, SearchText, StatisticsTes
operation_3 = models.Operation.objects.get(pk=self.operations[2].pk)
operation_1.common_name = "Opération : Château de Fougères"
operation_1.save()
- operation_2.common_name = "Opération : Fougère filicophyta et " "herbe à chat"
+ operation_2.common_name = "Opération : Fougère filicophyta et herbe à chat"
operation_2.save()
operation_3.common_name = "Opération : Château Filicophyta"
operation_3.save()
@@ -3348,6 +3348,11 @@ class OperationSearchTest(TestCase, OperationInitTest, SearchText, StatisticsTes
(f'{search_name_q}="Foug*" {search_name_q}="Jossel*"', 2),
]
self._test_search(c, result, context="Many name open search")
+ # open and precise search
+ result = [
+ (f'{search_name_q}="Foug*" {search_name_q}="Opération : Château de Josselin"', 2),
+ ]
+ self._test_search(c, result, context="Many name open search")
# non hierarchic search
search_remain_q = str(pgettext("key for text search", "remain"))
diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py
index eb37c9d62..40734a087 100644
--- a/ishtar_common/views_item.py
+++ b/ishtar_common/views_item.py
@@ -1695,7 +1695,7 @@ def _manage_relation_types(relation_types, dct, query, or_reqs):
if k.endswith("year"):
k += "__exact"
alt_dct[rtype_prefix + "right_relations__right_record__" + k] = val
- query |= Q(**alt_dct)
+ query |= Q(**__reapply_filters(alt_dct))
for k, or_req in or_reqs:
altor_dct = alt_dct.copy()
altor_dct.pop(k)
@@ -1704,10 +1704,23 @@ def _manage_relation_types(relation_types, dct, query, or_reqs):
if j == "year":
j = "year__exact"
altor_dct[rtype_prefix + "right_relations__right_record__" + j] = val
- query |= Q(**altor_dct)
+ query |= Q(**__reapply_filters(altor_dct))
return query
+def __reapply_filters(dct):
+ """
+ reapply filters "__iexact", "__icontains"
+ dct[k] = (filter, value) -> dct[k + filter] = value
+ """
+ new_dct = {}
+ for k, value in dct.items():
+ if isinstance(value, tuple):
+ k, value = k + value[0], value[1]
+ new_dct[k] = value
+ return new_dct
+
+
def _construct_query(relation_types, dct, or_reqs, and_reqs, excluded_relation=False):
# excluded -> reverse logic
if excluded_relation:
@@ -1724,17 +1737,31 @@ def _construct_query(relation_types, dct, or_reqs, and_reqs, excluded_relation=F
dct = {}
# manage multi value not already managed
+ # regroup same keys with different filters
+ filters = ("__iexact", "__icontains", "__isnull")
for key in list(dct.keys()):
- if isinstance(dct[key], str) and ";" in dct[key]:
- values = [v for v in dct[key].split(";") if v]
- if not values:
- dct.pop(key)
- continue
- dct[key] = values[0]
- if len(values) == 1:
- continue
- for v in values[1:]:
- or_reqs.append((key, {key: v}))
+ base_key, q_filter = key, ""
+ for filtr in filters:
+ if key.endswith(filtr):
+ base_key = key[:-len(filtr)]
+ q_filter = filtr
+ break
+ if not isinstance(dct[key], str):
+ continue
+ # if filter -> value = (filter, value)
+ values = [v if not q_filter else (q_filter, v)
+ for v in dct[key].split(";")]
+ dct.pop(key)
+ if not values:
+ continue
+ if base_key in dct:
+ or_reqs.append((base_key, {base_key: values[0]}))
+ else:
+ dct[base_key] = values[0]
+ if len(values) == 1:
+ continue
+ for v in values[1:]:
+ or_reqs.append((base_key, {base_key: v}))
for k in list(dct.keys()):
if type(k) not in (list, tuple):
@@ -1746,17 +1773,19 @@ def _construct_query(relation_types, dct, or_reqs, and_reqs, excluded_relation=F
for other_key in k[1:]:
or_reqs.append((first_key, {other_key: value}))
- query = Q(**dct)
+ # generate query
+ query = Q(**__reapply_filters(dct))
+
for or_req in or_reqs:
- alt_dct = dct.copy()
+ base_dct = dct.copy()
if isinstance(or_req, (tuple, list)):
k, or_req = or_req
- if k in alt_dct:
- alt_dct.pop(k)
- alt_dct.update(or_req)
- query |= Q(**alt_dct)
+ if k in base_dct:
+ base_dct.pop(k)
+ base_dct.update(or_req)
+ query |= Q(**__reapply_filters(base_dct))
else:
- query |= (Q(**alt_dct) & Q(or_req))
+ query |= (Q(**__reapply_filters(base_dct)) & Q(or_req))
query = _manage_relation_types(relation_types, dct, query, or_reqs)
done = []