summaryrefslogtreecommitdiff
path: root/ishtar_common
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2024-05-29 11:10:50 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2024-05-30 14:20:27 +0200
commitcb1e9f1f15c38f68c1859b2dfd67870b0ed81240 (patch)
tree415ec01bb56b837f5f951db06cd5a107a720f3fe /ishtar_common
parentd949cd7866446e30ca3c14926358fc91f1535ded (diff)
downloadIshtar-cb1e9f1f15c38f68c1859b2dfd67870b0ed81240.tar.bz2
Ishtar-cb1e9f1f15c38f68c1859b2dfd67870b0ed81240.zip
🐛 criteria search - towns - related model: fix * and - * (refs #5882)
Diffstat (limited to 'ishtar_common')
-rw-r--r--ishtar_common/models.py21
-rw-r--r--ishtar_common/models_common.py3
-rw-r--r--ishtar_common/views_item.py63
3 files changed, 70 insertions, 17 deletions
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index d13b2eaa2..c098eee02 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -2894,18 +2894,21 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem):
pgettext_lazy("key for text search", "email"), "email__iexact"
),
"title": SearchAltName(
- pgettext_lazy("key for text search", "title"), "title__label__iexact"
- ),
+ pgettext_lazy("key for text search", "title"), "title__label__iexact",
+ related_name="title"
+ ),
"salutation": SearchAltName(
pgettext_lazy("key for text search", "salutation"), "salutation__iexact"
),
"person_types": SearchAltName(
pgettext_lazy("key for text search", "type"),
"person_types__label__iexact",
+ related_name="person_types"
),
"attached_to": SearchAltName(
pgettext_lazy("key for text search", "organization"),
"attached_to__cached_label__iexact",
+ related_name="attached_to"
),
"ishtaruser__isnull": SearchAltName(
pgettext_lazy("key for text search", "has-account"),
@@ -4292,10 +4295,12 @@ class Document(
"authors": SearchAltName(
pgettext_lazy("key for text search", "author"),
"authors__cached_label__iexact",
+ related_name="authors"
),
"publisher": SearchAltName(
pgettext_lazy("key for text search", "publisher"),
"publisher__name__iexact",
+ related_name="publisher"
),
"publishing_year": SearchAltName(
pgettext_lazy("key for text search", "publishing-year"),
@@ -4321,11 +4326,13 @@ class Document(
"description__iexact",
),
"tag": SearchAltName(
- pgettext_lazy("key for text search", "tag"), "tags__label__iexact"
+ pgettext_lazy("key for text search", "tag"), "tags__label__iexact",
+ related_name="tags"
),
"format": SearchAltName(
pgettext_lazy("key for text search", "format"),
"format_type__label__iexact",
+ related_name="format_type"
),
"support": SearchAltName(
pgettext_lazy("key for text search", "medium"),
@@ -4338,6 +4345,7 @@ class Document(
"licenses": SearchAltName(
pgettext_lazy("key for text search", "license"),
"licenses__label__iexact",
+ related_name="licenses"
),
"rights_owner": SearchAltName(
pgettext_lazy("key for text search", "rights-owner"),
@@ -4352,6 +4360,7 @@ class Document(
"associated_url": SearchAltName(
pgettext_lazy("key for text search", "url"),
"associated_url__iexact",
+ related_name="associated_url"
),
"isbn": SearchAltName(
pgettext_lazy("key for text search", "isbn"), "isbn__iexact"
@@ -4388,6 +4397,7 @@ class Document(
"operation": SearchAltName(
pgettext_lazy("key for text search", "operation"),
"operations__cached_label__iexact",
+ related_name="operations"
),
"operations__operation_type": SearchAltName(
pgettext_lazy("key for text search", "operation-type"),
@@ -4400,14 +4410,17 @@ class Document(
"context_record": SearchAltName(
pgettext_lazy("key for text search", "context-record"),
"context_records__cached_label__iexact",
+ related_name="context_records"
),
"find_basket": SearchAltName(
pgettext_lazy("key for text search", "basket-finds"),
"finds__basket__label__iexact",
+ related_name="finds__basket"
),
"find": SearchAltName(
pgettext_lazy("key for text search", "find"),
"finds__cached_label__iexact",
+ related_name="finds"
),
"find__denomination": SearchAltName(
pgettext_lazy("key for text search", "find-denomination"),
@@ -4420,6 +4433,7 @@ class Document(
"containers": SearchAltName(
pgettext_lazy("key for text search", "container"),
"containers__cached_label__iexact",
+ related_name="containers"
),
"site": SearchAltName(
pgettext_lazy("key for text search", "site"),
@@ -4432,6 +4446,7 @@ class Document(
"town": SearchAltName(
pgettext_lazy("key for text search", "town"),
"towns__name__iexact",
+ related_name="towns"
),
"area": SearchAltName(
pgettext_lazy("key for text search", "area"),
diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py
index f58ff8f09..6abe515d6 100644
--- a/ishtar_common/models_common.py
+++ b/ishtar_common/models_common.py
@@ -1115,12 +1115,13 @@ class FullSearch(models.Model):
class SearchAltName(object):
def __init__(
- self, search_key, search_query, extra_query=None, distinct_query=False
+ self, search_key, search_query, extra_query=None, distinct_query=False, related_name=None
):
self.search_key = search_key
self.search_query = search_query
self.extra_query = extra_query or {}
self.distinct_query = distinct_query
+ self.related_name = related_name
class Imported(models.Model):
diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py
index 1a35e766e..9f2fbb7b5 100644
--- a/ishtar_common/views_item.py
+++ b/ishtar_common/views_item.py
@@ -753,6 +753,8 @@ def _parse_query_string(
dct = exc_dct
if query_parameters[base_term].extra_query:
dct.update(query_parameters[base_term].extra_query)
+ if query_parameters[base_term].related_name and query == '"*"':
+ term = query_parameters[base_term].related_name
if term in dct:
dct[term] += ";" + query
else:
@@ -1140,10 +1142,20 @@ def _manage_hierarchic_fields(model, dct, and_reqs):
suffix = "label__iexact"
else:
continue
-
val = _clean_type_val(dct.pop(req))
if val.startswith('"') and val.endswith('"'):
val = val[1:-1]
+ if val == "*":
+ req = req.replace("label__", "").replace("pk", "").replace("iexact", "")
+ req += "isnull"
+ reqs = Q(**{req: False})
+ and_reqs.append(reqs)
+ continue
+ elif "*" in val and "iexact" in suffix:
+ suffix = suffix.replace("iexact", "icontains")
+ req = req.replace("iexact", "icontains")
+ val = val.replace("*", "")
+
reqs = Q(**{req: val})
for idx in range(HIERARCHIC_LEVELS):
@@ -1154,12 +1166,18 @@ def _manage_hierarchic_fields(model, dct, and_reqs):
# TODO: improve query with "IN ()"?
continue
- if req.endswith("wcontainer_id") or req.endswith("wcontainer_ref_id"):
+ if req.endswith("wcontainer_id") or req.endswith("wcontainer_ref_id"):
val = _clean_type_val(dct.pop(req)).strip('"')
if val.startswith('"') and val.endswith('"'):
val = val[1:-1]
vals = [v.replace('"', "") for v in val.split(";")]
+ req = req[1:] # remove "w"
container_ids = []
+ if "*" in vals:
+ main_req = Q(**{req + "__isnull": False})
+ and_reqs.append(main_req)
+ continue
+
for val in vals:
q = Container.objects.filter(cached_label__iexact=val).values_list(
"id", flat=True)
@@ -1167,7 +1185,6 @@ def _manage_hierarchic_fields(model, dct, and_reqs):
continue
container_id = q.all()[0]
container_ids.append(container_id)
- req = req[1:] # remove "w"
main_req = Q(**{req + "__in": container_ids})
and_reqs.append(main_req)
@@ -1215,15 +1232,29 @@ def _manage_hierarchic_fields(model, dct, and_reqs):
vals = [v.replace('"', "") for v in val.split(";")]
main_req = None
for val in vals:
+ suf = suffix
+ if "*" == val:
+ req = req.replace("cached_label__", "").replace("pk", "").replace("iexact", "")
+ req += "isnull"
+ reqs = Q(**{req: False})
+ if not main_req:
+ main_req = reqs
+ else:
+ main_req |= reqs
+ continue
+ elif "*" in val and "iexact" in suf:
+ suf = suffix.replace("iexact", "icontains")
+ req = req.replace("iexact", "icontains")
+ val = val.replace("*", "")
reqs = Q(**{req: val})
nreq = base_req = req[:]
for idx in range(HIERARCHIC_LEVELS):
- nreq = nreq[: -(len(suffix))] + "parents__" + suffix
+ nreq = nreq[: -(len(suf))] + "parents__" + suf
q = Q(**{nreq: val})
reqs |= q
nreq = base_req[:]
for idx in range(HIERARCHIC_LEVELS):
- nreq = nreq[: -(len(suffix))] + "children__" + suffix
+ nreq = nreq[: -(len(suf))] + "children__" + suf
q = Q(**{nreq: val})
reqs |= q
if not main_req:
@@ -1311,21 +1342,24 @@ def _manage_hierarchic_fields(model, dct, and_reqs):
break
-def _manage_clean_search_field(dct, exclude=None, reverse=False):
+def _manage_clean_search_field(dct, exclude=None, reverse=False, related_name_fields=None):
+ related_names = related_name_fields if related_name_fields else []
for k in list(dct.keys()):
# clean quoted search field
- if type(dct[k]) != str:
+ if not isinstance(dct[k], str):
continue
dct[k] = dct[k].replace('"', "")
dct[k] = _clean_type_val(dct[k])
- if "*" not in dct[k] or not k.endswith("__iexact"):
+ if "*" not in dct[k] or k.endswith("regex"):
continue
value = dct.pop(k).strip()
- base_key = k[:-len("__iexact")]
+ base_key = k[:]
+ if k.endswith("__iexact"):
+ base_key = k[:-len("__iexact")]
if value == "*":
- if not reverse:
+ if k in related_names or not reverse:
dct[base_key + "__isnull"] = False
- if exclude is not None:
+ if exclude is not None and k.endswith("__iexact"):
exclude[base_key + "__exact"] = ""
continue
if value.startswith("*"):
@@ -2218,6 +2252,9 @@ def get_item(
if k not in query_parameters:
query_parameters[k] = SearchAltName(k, request_keys[k])
+ related_name_fields = [query_parameters[k].related_name for k in query_parameters
+ if query_parameters[k].related_name]
+
dct, excluded_dct, distinct_queries = _search_manage_search_vector(
model,
dct,
@@ -2273,8 +2310,8 @@ def get_item(
exc_and_reqs += dct.pop("exc_and_reqs")
updated_excluded = {}
- _manage_clean_search_field(dct, updated_excluded)
- _manage_clean_search_field(excluded_dct, dct, reverse=True)
+ _manage_clean_search_field(dct, updated_excluded, related_name_fields=related_name_fields)
+ _manage_clean_search_field(excluded_dct, dct, reverse=True, related_name_fields=related_name_fields)
if updated_excluded:
excluded_dct.update(updated_excluded)