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 | c573609f76f5d0081cde0727f52a69a62d388e10 (patch) | |
| tree | ec391d3cae5842a74159eb452cd52b404e1cf19e /ishtar_common/views_item.py | |
| parent | 0f48778cee5d7f47fac9163e6ce032a3f8b3821a (diff) | |
| download | Ishtar-c573609f76f5d0081cde0727f52a69a62d388e10.tar.bz2 Ishtar-c573609f76f5d0081cde0727f52a69a62d388e10.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 | 
