summaryrefslogtreecommitdiff
path: root/ishtar_common/views_item.py
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2019-01-31 17:06:29 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2019-01-31 17:06:29 +0100
commit7bc356efd27f625618dda25e0abde2fda30d9850 (patch)
tree013b56c339effd0a0540f5cee907986e30fd897a /ishtar_common/views_item.py
parentc72f6a2dfcc14607cac31c71e96128ea457428b3 (diff)
downloadIshtar-7bc356efd27f625618dda25e0abde2fda30d9850.tar.bz2
Ishtar-7bc356efd27f625618dda25e0abde2fda30d9850.zip
Search: manage dynamic query parameters (ex: divisions details)
Diffstat (limited to 'ishtar_common/views_item.py')
-rw-r--r--ishtar_common/views_item.py113
1 files changed, 80 insertions, 33 deletions
diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py
index 8af79c6fa..437bbd651 100644
--- a/ishtar_common/views_item.py
+++ b/ishtar_common/views_item.py
@@ -32,7 +32,7 @@ from weasyprint.fonts import FontConfiguration
from ishtar_common.utils import check_model_access_control, CSV_OPTIONS, \
get_all_field_names
from ishtar_common.models import HistoryError, get_current_profile, \
- PRIVATE_FIELDS, GeneralType
+ PRIVATE_FIELDS, GeneralType, SearchAltName
from menus import Menu
import models
@@ -381,21 +381,23 @@ FORBIDDEN_CHAR = [u":"]
RESERVED_CHAR = [u"|", u"&"]
-def _parse_query_string(string, request_keys, current_dct, exc_dct):
+def _parse_query_string(string, query_parameters, current_dct, exc_dct,
+ extra_distinct_q):
string = string.strip().lower()
if u"=" in string:
splited = string.split(u"=")
if len(splited) == 2:
- term, query = splited
- excluded = term.startswith(u"-")
+ base_term, query = splited
+ excluded = base_term.startswith(u"-")
if excluded:
- term = term[1:]
- if term in request_keys:
+ base_term = base_term[1:]
+ if base_term in query_parameters:
dct = current_dct
- term = request_keys[term]
+ term = query_parameters[base_term].search_query
# callable request key for complex queries
if callable(term):
+ # !! distinct_queries not managed
is_true = is_true_string(query)
if excluded:
is_true = not is_true
@@ -411,12 +413,26 @@ def _parse_query_string(string, request_keys, current_dct, exc_dct):
if cextra:
dct['extras'].append(cextra)
else:
- if excluded:
+ if query_parameters[base_term].distinct_query:
+ extra_distinct_q.append({})
+ dct = extra_distinct_q[-1]
+ if not query_parameters[base_term].distinct_query and \
+ excluded:
dct = exc_dct
+ if query_parameters[base_term].extra_query:
+ dct.update(query_parameters[base_term].extra_query)
if term in dct:
dct[term] += u";" + query
else:
dct[term] = query
+ if query_parameters[base_term].distinct_query:
+ for k in dct: # clean "
+ dct[k] = dct[k].replace('"', '')
+ # distinct query wait for a query
+ if excluded:
+ extra_distinct_q[-1] = ~Q(**dct)
+ else:
+ extra_distinct_q[-1] = Q(**dct)
return u""
for reserved_char in FORBIDDEN_CHAR:
string = string.replace(reserved_char, u"")
@@ -436,21 +452,24 @@ def _parse_query_string(string, request_keys, current_dct, exc_dct):
return string
-def _parse_parentheses_groups(groups, request_keys, current_dct=None,
- exc_dct=None):
+def _parse_parentheses_groups(groups, query_parameters, current_dct=None,
+ exc_dct=None, extra_distinct_q=None):
"""
Transform parentheses groups to query
:param groups: groups to transform (list)
- :param request_keys: request keys for facet search
+ :param query_parameters: query keys for facet search
:param current_dct: query dict
:param exc_dct: exclude query dict
+ :param exc_dct: exclude query dict
:return: query string, query dict, excluded query dict
"""
if not current_dct:
current_dct = {}
if not exc_dct:
exc_dct = {}
+ if not extra_distinct_q:
+ extra_distinct_q = []
if type(groups) is not list:
string = groups.strip()
if string.startswith(u'"') and string.endswith(u'"') and \
@@ -479,17 +498,19 @@ def _parse_parentheses_groups(groups, request_keys, current_dct=None,
string_groups = [gp.replace(SEP, u" ") for gp in string.split(u" ")]
if len(string_groups) == 1:
return _parse_query_string(
- string_groups[0], request_keys, current_dct, exc_dct), \
- current_dct, exc_dct
- return _parse_parentheses_groups(string_groups,
- request_keys, current_dct, exc_dct)
+ string_groups[0], query_parameters, current_dct, exc_dct,
+ extra_distinct_q
+ ), current_dct, exc_dct, extra_distinct_q
+ return _parse_parentheses_groups(
+ string_groups, query_parameters, current_dct, exc_dct,
+ extra_distinct_q)
if not groups: # empty list
- return "", current_dct, exc_dct
+ return "", current_dct, exc_dct, extra_distinct_q
query = u"("
previous_sep, has_item = None, False
for item in groups:
- q, current_dct, exc_dct = _parse_parentheses_groups(
- item, request_keys, current_dct, exc_dct)
+ q, current_dct, exc_dct, extra_distinct_q = _parse_parentheses_groups(
+ item, query_parameters, current_dct, exc_dct, extra_distinct_q)
q = q.strip()
if not q:
continue
@@ -509,18 +530,20 @@ def _parse_parentheses_groups(groups, request_keys, current_dct=None,
query += u")"
if query == u"()":
query = u""
- return unidecode(query), current_dct, exc_dct
+ return unidecode(query), current_dct, exc_dct, extra_distinct_q
-def _search_manage_search_vector(model, dct, exc_dct, request_keys):
+def _search_manage_search_vector(model, dct, exc_dct, distinct_queries,
+ query_parameters):
if 'search_vector' not in dct:
- return dct, exc_dct
+ return dct, exc_dct, distinct_queries
search_vector = dct['search_vector']
parentheses_groups = _parse_parentheses(search_vector)
- search_query, extra_dct, extra_exc_dct = _parse_parentheses_groups(
- parentheses_groups, request_keys)
+ search_query, extra_dct, extra_exc_dct, extra_distinct_q = \
+ _parse_parentheses_groups(parentheses_groups, query_parameters)
dct.update(extra_dct)
+ distinct_queries += extra_distinct_q
exc_dct.update(extra_exc_dct)
if search_query:
@@ -536,7 +559,7 @@ def _search_manage_search_vector(model, dct, exc_dct, request_keys):
'params': [settings.ISHTAR_SEARCH_LANGUAGE,
search_query]}
)
- return dct, exc_dct
+ return dct, exc_dct, distinct_queries
def _manage_bool_fields(model, bool_fields, reversed_bool_fields, dct, or_reqs):
@@ -1033,11 +1056,18 @@ def get_item(model, func_name, default_name, extra_request_keys=None,
else:
query_own = model.get_query_owns(q.all()[0])
+ query_parameters = {}
+
+ if hasattr(model, 'get_query_parameters'):
+ query_parameters = model.get_query_parameters()
+
# get defaults from model
- if not extra_request_keys and hasattr(model, 'EXTRA_REQUEST_KEYS'):
+ if not extra_request_keys and query_parameters:
my_extra_request_keys = copy(model.EXTRA_REQUEST_KEYS)
+ for key in query_parameters:
+ my_extra_request_keys[key] = query_parameters[key].search_query
else:
- my_extra_request_keys = copy(extra_request_keys or [])
+ my_extra_request_keys = copy(extra_request_keys or {})
if base_request is None and hasattr(model, 'BASE_REQUEST'):
if callable(model.BASE_REQUEST):
my_base_request = model.BASE_REQUEST(request)
@@ -1139,6 +1169,7 @@ def get_item(model, func_name, default_name, extra_request_keys=None,
excluded_dct = {}
and_reqs, or_reqs = [], []
exc_and_reqs, exc_or_reqs = [], []
+ distinct_queries = []
dct['extras'], dct['and_reqs'], dct['exc_and_reqs'] = [], [], []
if full == 'shortcut':
@@ -1158,11 +1189,19 @@ def get_item(model, func_name, default_name, extra_request_keys=None,
if not val:
continue
req_keys = request_keys[k]
+ target = dct
+ if k in query_parameters:
+ if query_parameters[k].distinct_query:
+ distinct_queries.append({})
+ target = distinct_queries[-1]
+ if query_parameters[k].extra_query:
+ target.update(query_parameters[k].extra_query)
+
if callable(req_keys):
# callable request key for complex queries not managed on GET
continue
elif type(req_keys) not in (list, tuple):
- dct[req_keys] = val
+ target[req_keys] = val
continue
# multiple choice target
reqs = Q(**{req_keys[0]: val})
@@ -1184,8 +1223,14 @@ def get_item(model, func_name, default_name, extra_request_keys=None,
else:
request.session[func_name] = dct
- dct, excluded_dct = _search_manage_search_vector(
- model, dct, excluded_dct, request_keys)
+ for k in request_keys:
+ if k not in query_parameters:
+ query_parameters[k] = SearchAltName(k, request_keys[k])
+
+ 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')
@@ -1254,9 +1299,12 @@ def get_item(model, func_name, default_name, extra_request_keys=None,
if current:
dct = {upper_key: current}
query &= Q(**dct)
-
# print(query)
items = model.objects.filter(query)
+ for d_q in distinct_queries:
+ print(d_q)
+ items = items.filter(d_q)
+
if base_query:
items = items.filter(base_query)
if exc_query:
@@ -1422,9 +1470,8 @@ def get_item(model, func_name, default_name, extra_request_keys=None,
keys = [keys]
my_vals = []
for k in keys:
- if hasattr(model, 'EXTRA_REQUEST_KEYS') \
- and k in model.EXTRA_REQUEST_KEYS:
- k = model.EXTRA_REQUEST_KEYS[k]
+ if k in my_extra_request_keys:
+ k = my_extra_request_keys[k]
if type(k) in (list, tuple):
k = k[0]
for filtr in ('__icontains', '__contains', '__iexact',