diff options
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 |
commit | cb1e9f1f15c38f68c1859b2dfd67870b0ed81240 (patch) | |
tree | 415ec01bb56b837f5f951db06cd5a107a720f3fe /ishtar_common | |
parent | d949cd7866446e30ca3c14926358fc91f1535ded (diff) | |
download | Ishtar-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.py | 21 | ||||
-rw-r--r-- | ishtar_common/models_common.py | 3 | ||||
-rw-r--r-- | ishtar_common/views_item.py | 63 |
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) |