diff options
Diffstat (limited to 'ishtar_common/views_item.py')
| -rw-r--r-- | ishtar_common/views_item.py | 113 | 
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', | 
