summaryrefslogtreecommitdiff
path: root/ishtar_common/views_item.py
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2024-10-28 12:22:50 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2025-02-19 14:43:48 +0100
commitebc72b876824b333bed368afaf3f700736b6b390 (patch)
treeebae3b2706c0fc13042b59f07fc63deda106de18 /ishtar_common/views_item.py
parent4f60b4805a7eac04c2a8ec2116a245dbeec3c822 (diff)
downloadIshtar-ebc72b876824b333bed368afaf3f700736b6b390.tar.bz2
Ishtar-ebc72b876824b333bed368afaf3f700736b6b390.zip
✨ search add OR "||" - search refactoring
Diffstat (limited to 'ishtar_common/views_item.py')
-rw-r--r--ishtar_common/views_item.py308
1 files changed, 181 insertions, 127 deletions
diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py
index b5c63cc65..48b83e654 100644
--- a/ishtar_common/views_item.py
+++ b/ishtar_common/views_item.py
@@ -1560,6 +1560,8 @@ def _manage_direct_id(dct):
Manage "id:1234" syntax
"""
for k, v in list(dct.items()):
+ if not isinstance(v, str):
+ continue
m = RE_ID.match(v)
if not m:
continue
@@ -1951,6 +1953,147 @@ def _get_table_cols(data_type, own_table_cols, full, model):
return table_cols
+def split_dict(dct):
+ if not dct.get("search_vector", None):
+ return [dct]
+ new_dcts = []
+ for vector in dct["search_vector"].split(" || "):
+ new_dct = deepcopy(dct)
+ new_dct["search_vector"] = vector
+ new_dcts.append(new_dct)
+ return new_dcts
+
+
+def main_manager(
+ request, model, query_own, full, dct, distinct_queries, query_parameters,
+ my_relation_types_prefix, my_bool_fields, my_reversed_bool_fields,
+ related_name_fields, many_counted_fields, reversed_many_counted_fields,
+ my_dated_fields, my_number_fields, and_reqs
+ ):
+ excluded_dct = {}
+ or_reqs = []
+ exc_and_reqs, exc_or_reqs = [], []
+ dct, excluded_dct, distinct_queries = _search_manage_search_vector(
+ model,
+ dct,
+ excluded_dct,
+ distinct_queries,
+ query_parameters,
+ )
+
+ if "search_vector" in dct:
+ dct.pop("search_vector")
+
+ # manage relations types
+ if "relation_types" not in my_relation_types_prefix:
+ my_relation_types_prefix["relation_types"] = ""
+
+ relation_types = _get_relation_type_dict(my_relation_types_prefix, dct)
+ exc_relation_types = _get_relation_type_dict(my_relation_types_prefix,
+ excluded_dct)
+
+ _manage_bool_fields(
+ model, my_bool_fields, my_reversed_bool_fields, dct, or_reqs
+ )
+ _manage_bool_fields(
+ model, my_bool_fields, my_reversed_bool_fields, excluded_dct, exc_or_reqs
+ )
+
+ tmp_excluded = {}
+ _manage_many_counted_fields(
+ many_counted_fields, reversed_many_counted_fields, dct, tmp_excluded
+ )
+ _manage_many_counted_fields(
+ many_counted_fields, reversed_many_counted_fields, excluded_dct, dct
+ )
+ if tmp_excluded:
+ excluded_dct.update(tmp_excluded)
+
+ # dated_fields, number_fields
+ # ['signature_date', ...], ['signature_date__year', ...]
+ # -> remove 'signature_date'
+ filtered_dated_fields = []
+ for field_name in my_dated_fields:
+ exc = False
+ for number_field in my_number_fields:
+ if number_field.startswith(field_name):
+ exc = True
+ break
+ if not exc:
+ filtered_dated_fields.append(field_name)
+ my_dated_fields = filtered_dated_fields
+
+ _manage_dated_fields(my_dated_fields, dct)
+ _manage_dated_fields(my_dated_fields, excluded_dct)
+
+ _manage_number_fields(my_number_fields, dct)
+ _manage_number_fields(my_number_fields, excluded_dct)
+
+ _manage_hierarchic_fields(model, dct, and_reqs)
+ _manage_hierarchic_fields(model, excluded_dct, exc_and_reqs)
+
+ _manage_facet_search(model, dct, and_reqs)
+ _manage_facet_search(model, excluded_dct, exc_and_reqs)
+
+ extras = []
+ if "extras" in dct:
+ extras = dct.pop("extras")
+ if "and_reqs" in dct:
+ and_reqs += dct.pop("and_reqs")
+ if "exc_and_reqs" in dct:
+ exc_and_reqs += dct.pop("exc_and_reqs")
+
+ updated_excluded = {}
+ _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)
+
+ # manage direct ID 'id:1234' syntax - used by "{USER}" search
+ _manage_direct_id(dct)
+ _manage_direct_id(excluded_dct)
+
+ query = _construct_query(relation_types, dct, or_reqs, and_reqs)
+ exc_query = None
+ if excluded_dct or exc_and_reqs or exc_or_reqs or exc_relation_types:
+ exc_query = _construct_query(
+ exc_relation_types, excluded_dct, exc_or_reqs, exc_and_reqs,
+ excluded_relation=True
+ )
+
+ if query_own:
+ query = query & query_own
+
+ # manage hierarchic in shortcut menu
+ if full == "shortcut":
+ query = manage_hierarchy_shorcut(model, request, query)
+ return query, exc_query, extras
+
+
+def manage_hierarchy_shorcut(model, request, query):
+ File = apps.get_model("archaeological_files", "File")
+ Operation = apps.get_model("archaeological_operations", "Operation")
+ ContextRecord = apps.get_model("archaeological_context_records", "ContextRecord")
+ Find = apps.get_model("archaeological_finds", "Find")
+ ASSOCIATED_ITEMS = {
+ Operation: (File, "associated_file__pk"),
+ ContextRecord: (Operation, "operation__pk"),
+ Find: (ContextRecord, "base_finds__context_record__pk"),
+ }
+ if model in ASSOCIATED_ITEMS:
+ upper_model, upper_key = ASSOCIATED_ITEMS[model]
+ model_name = upper_model.SLUG
+ current = model_name in request.session and request.session[model_name]
+ if current:
+ dct = {upper_key: current}
+ query &= Q(**dct)
+ return query
+
+
DEFAULT_ROW_NUMBER = 10
# length is used by ajax DataTables requests
EXCLUDED_FIELDS = ["length"]
@@ -2253,9 +2396,7 @@ def get_item(
dct = {}
else:
dct = copy(my_base_request)
- excluded_dct = {}
- and_reqs, or_reqs = [], []
- exc_and_reqs, exc_or_reqs = [], []
+ and_reqs = []
distinct_queries = []
dct["extras"], dct["and_reqs"], dct["exc_and_reqs"] = [], [], []
@@ -2352,128 +2493,44 @@ def get_item(
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,
- excluded_dct,
- distinct_queries,
- query_parameters,
- )
- search_vector = ""
- if "search_vector" in dct:
- search_vector = dct.pop("search_vector")
-
- # manage relations types
- if "relation_types" not in my_relation_types_prefix:
- my_relation_types_prefix["relation_types"] = ""
-
- relation_types = _get_relation_type_dict(my_relation_types_prefix, dct)
- exc_relation_types = _get_relation_type_dict(my_relation_types_prefix,
- excluded_dct)
-
- _manage_bool_fields(
- model, my_bool_fields, my_reversed_bool_fields, dct, or_reqs
- )
- _manage_bool_fields(
- model, my_bool_fields, my_reversed_bool_fields, excluded_dct, exc_or_reqs
- )
-
- tmp_excluded = {}
- _manage_many_counted_fields(
- many_counted_fields, reversed_many_counted_fields, dct, tmp_excluded
- )
- _manage_many_counted_fields(
- many_counted_fields, reversed_many_counted_fields, excluded_dct, dct
- )
- if tmp_excluded:
- excluded_dct.update(tmp_excluded)
-
- # dated_fields, number_fields
- # ['signature_date', ...], ['signature_date__year', ...]
- # -> remove 'signature_date'
- filtered_dated_fields = []
- for field_name in my_dated_fields:
- exc = False
- for number_field in my_number_fields:
- if number_field.startswith(field_name):
- exc = True
- break
- if not exc:
- filtered_dated_fields.append(field_name)
- my_dated_fields = filtered_dated_fields
-
- _manage_dated_fields(my_dated_fields, dct)
- _manage_dated_fields(my_dated_fields, excluded_dct)
-
- _manage_number_fields(my_number_fields, dct)
- _manage_number_fields(my_number_fields, excluded_dct)
-
- _manage_hierarchic_fields(model, dct, and_reqs)
- _manage_hierarchic_fields(model, excluded_dct, exc_and_reqs)
-
- _manage_facet_search(model, dct, and_reqs)
- _manage_facet_search(model, excluded_dct, exc_and_reqs)
-
- extras = []
- if "extras" in dct:
- extras = dct.pop("extras")
- if "and_reqs" in dct:
- and_reqs += dct.pop("and_reqs")
- if "exc_and_reqs" in dct:
- exc_and_reqs += dct.pop("exc_and_reqs")
-
- updated_excluded = {}
- _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)
-
- # manage direct ID 'id:1234' syntax - used by "{USER}" search
- _manage_direct_id(dct)
- _manage_direct_id(excluded_dct)
-
- query = _construct_query(relation_types, dct, or_reqs, and_reqs)
- exc_query = None
- if excluded_dct or exc_and_reqs or exc_or_reqs or exc_relation_types:
- exc_query = _construct_query(
- exc_relation_types, excluded_dct, exc_or_reqs, exc_and_reqs,
- excluded_relation=True
+ items = None
+ for sub_dct in split_dict(dct):
+ query, exc_query, extras = main_manager(
+ request,
+ model,
+ query_own,
+ full,
+ sub_dct,
+ distinct_queries,
+ query_parameters,
+ my_relation_types_prefix,
+ my_bool_fields,
+ my_reversed_bool_fields,
+ related_name_fields,
+ many_counted_fields,
+ reversed_many_counted_fields,
+ my_dated_fields,
+ my_number_fields,
+ and_reqs
)
- if query_own:
- query = query & query_own
-
- # manage hierarchic in shortcut menu
- if full == "shortcut":
- File = apps.get_model("archaeological_files", "File")
- Operation = apps.get_model("archaeological_operations", "Operation")
- ContextRecord = apps.get_model("archaeological_context_records", "ContextRecord")
- Find = apps.get_model("archaeological_finds", "Find")
- ASSOCIATED_ITEMS = {
- Operation: (File, "associated_file__pk"),
- ContextRecord: (Operation, "operation__pk"),
- Find: (ContextRecord, "base_finds__context_record__pk"),
- }
- if model in ASSOCIATED_ITEMS:
- upper_model, upper_key = ASSOCIATED_ITEMS[model]
- model_name = upper_model.SLUG
- current = model_name in request.session and request.session[model_name]
- if current:
- dct = {upper_key: current}
- query &= Q(**dct)
- # print("ishtar_common/views_item.py - 2455")
- # print(query, distinct_queries, base_query, exc_query, extras)
- items = model.objects.filter(query)
- for d_q in distinct_queries:
- items = items.filter(d_q)
-
- if base_query:
- items = items.filter(base_query)
- if exc_query:
- items = items.exclude(exc_query)
-
- for extra in extras:
- items = items.extra(**extra)
+ # print("ishtar_common/views_item.py - 2515")
+ # print(query, distinct_queries, base_query, exc_query, extras)
+ sub_items = model.objects.filter(query)
+ for d_q in distinct_queries:
+ sub_items = sub_items.filter(d_q)
+
+ if base_query:
+ sub_items = sub_items.filter(base_query)
+ if exc_query:
+ sub_items = sub_items.exclude(exc_query)
+
+ for extra in extras:
+ sub_items = sub_items.extra(**extra)
+ if not items:
+ items = sub_items
+ else:
+ items |= sub_items
if return_query:
return items
@@ -2502,9 +2559,6 @@ def get_item(
return items_nb
# print(str(items.values("id").query))
- if search_vector: # for serialization
- dct["search_vector"] = search_vector
-
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)
@@ -2734,7 +2788,7 @@ def get_item(
lock = '&nbsp;<i class="fa fa-lock text-danger" aria-hidden="true"></i>'
own_lock = '&nbsp;<i class="fa fa-lock text-success" ' 'aria-hidden="true"></i>'
has_locks = hasattr(model, "locked")
- current_user_id = request.user and request.user.id
+ current_user_id = request and request.user and request.user.id
if data_type.startswith("json"):
rows = []
if data_type == "json-map":