From 83ed4687677954c6411b0ac9e9bdfc9f303251e0 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Fri, 31 Dec 2021 13:54:50 +0100 Subject: [PATCH] Filtering search results. --- .../catalogue/search_multiple_hits.html | 70 ++++++++++++++++ src/search/mock_search.py | 12 +-- src/search/templatetags/set_get_parameter.py | 49 ++++++++++++ src/search/views.py | 79 +++++++++++++++++-- src/wolnelektury/static/scss/main/search.scss | 17 ++++ 5 files changed, 214 insertions(+), 13 deletions(-) create mode 100644 src/search/templatetags/set_get_parameter.py diff --git a/src/catalogue/templates/catalogue/search_multiple_hits.html b/src/catalogue/templates/catalogue/search_multiple_hits.html index 4a32706ce..137175d80 100644 --- a/src/catalogue/templates/catalogue/search_multiple_hits.html +++ b/src/catalogue/templates/catalogue/search_multiple_hits.html @@ -3,12 +3,82 @@ {% load pagination_tags %} {% load inline_tag_list from catalogue_tags %} {% load book_searched from search_tags %} +{% load set_get_parameter %} {% block titleextra %}{% trans "Search" %}{% endblock %} {% block bodyid %}tagged-object-list{% endblock %} {% block body %} + +

{% trans "Search" %}

+ +
+ +

+ format: + {% if not set.format %}dowolny{% else %}dowolny{% endif %} + {% if set.format == "tekst" %}tekst{% else %}tekst{% endif %} + {% if set.format == "audio" %}audiobook{% else %}tekst{% endif %} + {% if set.format == "synchro" %}DAISY{% else %}DAISY{% endif %} + {% if set.format == "obraz" %}obraz{% else %}obraz{% endif %} +

+ +

+ {% trans "language" %}: + {% if not set.lang %}dowolny{% else %}dowolny{% endif %} + {% if set.lang == "pol" %}polski{% else %}polski{% endif %} + {% if set.lang == "eng" %}angielski{% else %}angielski{% endif %} + {% if set.lang == "fre" %}francuski{% else %}francuski{% endif %} + {% if set.lang == "ger" %}niemiecki{% else %}niemiecki{% endif %} + {% if set.lang == "lit" %}litewski{% else %}litewski{% endif %} +

+ +

+

+ {% trans "epoch" %}: + {% if not set.epoch %}dowolna{% else %}dowolna{% endif %} + {% for tag in tags.epoch %} + {% if set.epoch == tag.slug %} + {{ tag.name }} + {% else %} + + {{ tag.name }} + + {% endif %} + {% endfor %} +

+

+ {% trans "kind" %}: + {% if not set.kind %}dowolny{% else %}dowolny{% endif %} + {% for tag in tags.kind %} + {% if set.kind == tag.slug %} + {{ tag.name }} + {% else %} + + {{ tag.name }} + + {% endif %} + {% endfor %} +

+ + {% comment %} +

+ {% trans "genre" %}: + {% if not set.genre %}dowolny{% else %}dowolny{% endif %} + {% for tag in tags.genre %} + {% if set.genre == tag.slug %} + {{ tag.name }} + {% else %} + + {{ tag.name }} + + {% endif %} + {% endfor %} +

+ {% endcomment %} +
+ {% if did_you_mean %} {% trans "Did you mean" %} {{did_you_mean|lower}}? diff --git a/src/search/mock_search.py b/src/search/mock_search.py index 118078f9d..33d2a5eaf 100644 --- a/src/search/mock_search.py +++ b/src/search/mock_search.py @@ -19,10 +19,13 @@ class Search(Mock): index = MockIndex() - @staticmethod - def _find_some_books(query_terms=None, max_results=20): + def search_words(self, words, fields, required=None, book=True, picture=False): from .index import SearchResult + max_results = 20 + + if picture: return [] + qs = Book.objects.filter(findable=True).order_by('?') results = [] for book in qs[:randint(1, max_results)]: @@ -31,10 +34,7 @@ class Search(Mock): 'book_id': book.pk, 'published_date': randint(1000, 1920), } - res = SearchResult(doc, how_found='mock', query_terms=query_terms) + res = SearchResult(doc, how_found='mock', query_terms=words) results.append(res) return results - def search_everywhere(self, searched, query_terms=None): - return [] - diff --git a/src/search/templatetags/set_get_parameter.py b/src/search/templatetags/set_get_parameter.py new file mode 100644 index 000000000..36e22454e --- /dev/null +++ b/src/search/templatetags/set_get_parameter.py @@ -0,0 +1,49 @@ +# This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from re import split + +from django import template + +register = template.Library() + + +""" +In template: + {% set_get_paramater param1='const_value',param2=,param3=variable %} +results with changes to query string: + param1 is set to `const_value' string + param2 is unset, if exists, + param3 is set to the value of variable in context + +Using 'django.core.context_processors.request' is required. + +""" + + +class SetGetParameter(template.Node): + def __init__(self, values): + self.values = values + + def render(self, context): + request = template.Variable('request').resolve(context) + params = request.GET.copy() + for key, value in self.values.items(): + if value == '': + if key in params: + del(params[key]) + else: + params[key] = template.Variable(value).resolve(context) + return '?%s' % params.urlencode() + + +@register.tag +def set_get_parameter(parser, token): + parts = split(r'\s+', token.contents, 2) + + values = {} + for pair in parts[1].split(','): + s = pair.split('=') + values[s[0]] = s[1] + + return SetGetParameter(values) diff --git a/src/search/views.py b/src/search/views.py index da3a767f8..e06b1cc48 100644 --- a/src/search/views.py +++ b/src/search/views.py @@ -115,6 +115,13 @@ def hint(request, mozhint=False, param='term'): @cache.never_cache def main(request): query = request.GET.get('q', '') + + format = request.GET.get('format') + lang = request.GET.get('lang') + epoch = request.GET.get('epoch') + kind = request.GET.get('kind') + genre = request.GET.get('genre') + if len(query) < 2: return render( request, 'catalogue/search_too_short.html', @@ -125,9 +132,32 @@ def main(request): {'prefix': query}) query = prepare_query(query) - pd_authors = search_pd_authors(query) - books = search_books(query) - pictures = search_pictures(query) + if not (format or lang or epoch or kind or genre): + pd_authors = search_pd_authors(query) + else: + pd_authors = [] + if not format or format != 'obraz': + books = search_books( + query, + lang=lang, + only_audio=format=='audio', + only_synchro=format=='synchro', + epoch=epoch, + kind=kind, + genre=genre + ) + else: + books = [] + if (not format or format == 'obraz') and not lang: + pictures = search_pictures( + query, + epoch=epoch, + kind=kind, + genre=genre + ) + else: + pictures = [] + suggestion = '' if not (books or pictures or pd_authors): @@ -150,10 +180,22 @@ def main(request): 'pd_authors': pd_authors, 'books': books, 'pictures': pictures, - 'did_you_mean': suggestion + 'did_you_mean': suggestion, + 'set': { + 'lang': lang, + 'format': format, + 'epoch': epoch, + 'kind': kind, + 'genre': genre, + }, + 'tags': { + 'epoch': Tag.objects.filter(category='epoch'), + 'genre': Tag.objects.filter(category='genre'), + 'kind': Tag.objects.filter(category='kind'), + }, }) -def search_books(query): +def search_books(query, lang=None, only_audio=False, only_synchro=False, epoch=None, kind=None, genre=None): search = Search() results_parts = [] search_fields = [] @@ -185,15 +227,31 @@ def search_books(query): def ensure_exists(r): try: - return r.book + r.book except Book.DoesNotExist: return False + print(lang, r.book.language) + if lang and r.book.language != lang: + return False + if only_audio and not r.book.has_mp3_file(): + return False + if only_synchro and not r.book.has_daisy_file(): + return False + if epoch and not r.book.tags.filter(category='epoch', slug=epoch).exists(): + return False + if kind and not r.book.tags.filter(category='kind', slug=kind).exists(): + return False + if genre and not r.book.tags.filter(category='genre', slug=genre).exists(): + return False + + return True + results = [r for r in results if ensure_exists(r)] return results -def search_pictures(query): +def search_pictures(query, epoch=None, kind=None, genre=None): search = Search() results_parts = [] search_fields = [] @@ -224,6 +282,13 @@ def search_pictures(query): except Picture.DoesNotExist: return False + if epoch and not r.picture.tags.filter(category='epoch', slug=epoch).exists(): + return False + if kind and not r.picture.tags.filter(category='kind', slug=kind).exists(): + return False + if genre and not r.picture.tags.filter(category='genre', slug=genre).exists(): + return False + results = [r for r in results if ensure_exists(r)] return results diff --git a/src/wolnelektury/static/scss/main/search.scss b/src/wolnelektury/static/scss/main/search.scss index 3d992b368..6017d2182 100644 --- a/src/wolnelektury/static/scss/main/search.scss +++ b/src/wolnelektury/static/scss/main/search.scss @@ -125,3 +125,20 @@ //@include size(width, 275px); line-height: 1.636em; } + + + + +.search-filter { + a { + margin-right: 1em; + } + strong { + display: inline-block; + width: 5em; + } + em { + margin-right: 1em; + } + +} -- 2.20.1