diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-05-16 16:39:55 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-05-16 16:39:55 +0200 |
commit | 5738a774bf97ae8873064db7bfe3e99c1c7baef8 (patch) | |
tree | ec391d3cae5842a74159eb452cd52b404e1cf19e /ishtar_common/views_item.py | |
parent | 360499ade4c11cc19429806ead5f86488b4a5b6e (diff) | |
download | Ishtar-5738a774bf97ae8873064db7bfe3e99c1c7baef8.tar.bz2 Ishtar-5738a774bf97ae8873064db7bfe3e99c1c7baef8.zip |
Autocomplete: filter by more relevant search term
Diffstat (limited to 'ishtar_common/views_item.py')
-rw-r--r-- | ishtar_common/views_item.py | 69 |
1 files changed, 49 insertions, 20 deletions
diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index 57d778459..96190f083 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +from collections import OrderedDict from copy import copy, deepcopy import csv import datetime @@ -67,33 +68,61 @@ CURRENT_ITEM_KEYS = ( CURRENT_ITEM_KEYS_DICT = dict(CURRENT_ITEM_KEYS) -def get_autocomplete_query(request, label_attributes, extra=None): - q = request.GET.get('term') or "" +def get_autocomplete_queries(request, label_attributes, extra=None): if not label_attributes: - return Q(pk__isnull=True) - query = Q() - if extra: - query = Q(**extra) - for q in q.split(' '): - if not q: - continue - sub_q = Q(**{label_attributes[0] + "__icontains": q}) - for other_label in label_attributes[1:]: - sub_q = sub_q | Q(**{other_label + "__icontains": q}) - query = query & sub_q - return query + return [Q(pk__isnull=True)] + base_q = request.GET.get('term') or "" + queries = [] + splited_q = base_q.split(' ') + for value_prefix, query_suffix, query_endswith in ( + ('', '__startswith', True), # starts with + (' ', '__icontains', True), # contain a word which starts with + ('', '__endswith', False), # ends with + ('', '__icontains', False)): # contains + alt_queries = [None] + if len(splited_q) == 1 and query_endswith: + alt_queries = ["__endswith", None] + for alt_query in alt_queries: + query = Q() + if extra: + query = Q(**extra) + for q in splited_q: + if not q: + continue + sub_q = Q( + **{label_attributes[0] + query_suffix: value_prefix + q}) + if alt_query: + sub_q &= Q( + **{label_attributes[0] + alt_query: q} + ) + for other_label in label_attributes[1:]: + sub_q = sub_q | Q( + **{other_label + query_suffix: value_prefix + q}) + query = query & sub_q + queries.append(query) + return queries def get_autocomplete_item(model, extra=None): if not extra: extra = {} - def func(request, current_right=None): - query = get_autocomplete_query(request, ['cached_label'], extra=extra) - limit = 20 - objects = model.objects.filter(query)[:limit] - data = json.dumps([{'id': obj.pk, 'value': obj.cached_label} - for obj in objects]) + def func(request, current_right=None, limit=20): + result = OrderedDict() + for query in get_autocomplete_queries(request, ['cached_label'], + extra=extra): + objects = model.objects.filter(query).values( + 'cached_label', 'id')[:limit] + for obj in objects: + if obj["id"] not in list(result.keys()): + result[obj["id"]] = obj["cached_label"] + limit -= 1 + if not limit: + break + if not limit: + break + data = json.dumps([{'id': obj[0], 'value': obj[1]} + for obj in list(result.items())]) return HttpResponse(data, content_type='text/plain') return func |