diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2021-04-28 11:21:45 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2021-04-28 11:24:37 +0200 |
commit | 82097e9a5bf31134a8a3cff2bfc06337d529f878 (patch) | |
tree | 27b5941fde7db58fccb6af62f998a0ca80a7fe25 /archaeological_warehouse/views.py | |
parent | 032bb50d9da39e84ffb275c115cad0487881b5ec (diff) | |
download | Ishtar-82097e9a5bf31134a8a3cff2bfc06337d529f878.tar.bz2 Ishtar-82097e9a5bf31134a8a3cff2bfc06337d529f878.zip |
Container autocomplete: unaccent - any order of container types
Diffstat (limited to 'archaeological_warehouse/views.py')
-rw-r--r-- | archaeological_warehouse/views.py | 61 |
1 files changed, 33 insertions, 28 deletions
diff --git a/archaeological_warehouse/views.py b/archaeological_warehouse/views.py index 4fa60ff89..c6072a4df 100644 --- a/archaeological_warehouse/views.py +++ b/archaeological_warehouse/views.py @@ -18,6 +18,7 @@ # See the file COPYING for details. import json +from unidecode import unidecode from django.core.urlresolvers import reverse from django.db.models import Q @@ -143,33 +144,34 @@ def autocomplete_container(request, warehouse_id=None): ) limit = 15 - len(containers) splitted = [s.lower() for s in term.split(" ") if s and s != "|"] + unaccent_splitted = [unidecode(s).lower() for s in term.split(" ") + if s and s != "|"] if limit > 0 and len(splitted) > 1: type_positions = [] # container_type ID, pos inf, pos sup container_types = [ - (c[0], c[1]) + (c[0], unidecode(c[1]).lower()) for c in models.ContainerType.objects.values_list("id", "label") ] for container_type_id, value in container_types: - if value.lower() in term.lower(): # container_type is in search q - values = [v.lower() for v in value.split(" ") if v] - + if value in unidecode(term).lower(): # container_type is in search q + values = [unidecode(v.lower()) for v in value.split(" ") if v] # verify that all term match in splitted try: - index = splitted.index(values[0].lower()) + index = unaccent_splitted.index(values[0]) except ValueError: index = None index_is_ok = False while not index_is_ok and index is not None: for idx, v in enumerate(values): try: - assert splitted[index + idx] == v + assert unaccent_splitted[index + idx] == v except (ValueError, AssertionError): break index_is_ok = True if not index_is_ok: try: - index = splitted.index(values[0].lower(), index + 1) + index = unaccent_splitted.index(values[0], index + 1) except ValueError: index = None if index_is_ok: @@ -182,27 +184,30 @@ def autocomplete_container(request, warehouse_id=None): for idx in range(type_positions[0][1]): query &= Q(location__name__icontains=splitted[idx]) # group by container type, ref tuple - groups = [] - for idx, (container_type_id, pos_inf, pos_sup) in enumerate(type_positions): - if len(type_positions) == idx + 1: # last - value = " ".join(splitted[pos_sup:]) - else: - value = " ".join(splitted[pos_sup : type_positions[idx + 1][1]]) - if value: - groups.append((container_type_id, value)) - if groups: - query = base_query - for idx, g in enumerate(reversed(groups)): - base_key = "parent__" * idx - key1 = base_key + "container_type_id" - key2 = base_key + "reference__unaccent__iexact" - query &= Q(**{key1: g[0], key2: g[1]}) - ids = {c["id"] for c in containers} - containers += list( - models.Container.objects.filter(query) - .exclude(pk__in=ids) - .values("id", "cached_label")[:limit] - ) + # can be in any order + for positions in (type_positions, list(reversed(type_positions))): + groups = [] + for idx, (container_type_id, pos_inf, pos_sup) in enumerate(positions): + if len(positions) == idx + 1: # last + value = " ".join(splitted[pos_sup:]) + else: + value = " ".join(splitted[pos_sup:positions[idx + 1][1]]) + if value: + groups.append((container_type_id, value)) + if groups: + for gp in (groups, reversed(groups)): + query = base_query + for idx, g in enumerate(gp): + base_key = "parent__" * idx + key1 = base_key + "container_type_id" + key2 = base_key + "reference__unaccent__iexact" + query &= Q(**{key1: g[0], key2: g[1]}) + ids = {c["id"] for c in containers} + containers += list( + models.Container.objects.filter(query) + .exclude(pk__in=ids) + .values("id", "cached_label")[:limit] + ) if len(splitted) > 1 and len(containers) < 15: # group to do a "type" "reference" search |