X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/08e687e53ba84afd39646185142e59c6bfe77783..84a3f7f335bf15b4671cc56c26d243bf539a9536:/src/search/forms.py diff --git a/src/search/forms.py b/src/search/forms.py index 4fa051d7a..7efd7479d 100644 --- a/src/search/forms.py +++ b/src/search/forms.py @@ -1,10 +1,13 @@ # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # +from django.apps import apps +from django.contrib.postgres.search import SearchHeadline, SearchRank, SearchQuery from django import forms from django.utils.translation import gettext_lazy as _ -from search.fields import JQueryAutoCompleteSearchField +from .fields import JQueryAutoCompleteSearchField, InlineRadioWidget +from .utils import build_search_query class SearchForm(forms.Form): @@ -19,3 +22,148 @@ class SearchForm(forms.Form): self.fields['q'].widget.attrs['data-source'] = source if 'q' not in self.data: self.fields['q'].widget.attrs['placeholder'] = _('title, author, epoch, kind, genre, phrase') + + +class SearchFilters(forms.Form): + q = forms.CharField(required=False, widget=forms.HiddenInput()) + format = forms.ChoiceField(required=False, choices=[ + ('', 'wszystkie'), + ('text', 'tekst'), + ('audio', 'audiobook'), + ('daisy', 'Daisy'), + ('art', 'obraz'), + #('theme', 'motywy'), + ], widget=InlineRadioWidget()) + lang = forms.ChoiceField(required=False) + epoch = forms.ChoiceField(required=False) + genre = forms.ChoiceField(required=False) + category = forms.ChoiceField(required=False, choices=[ + ('', 'wszystkie'), + ('author', 'autor'), + #('translator', 'tłumacz'), + ('theme', 'motyw'), + ('genre', 'gatunek'), + ('book', 'tytuł'), + ('art', 'obraz'), + ('collection', 'kolekcja'), + ('quote', 'cytat'), + ], widget=InlineRadioWidget()) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + from catalogue.models import Book, Tag + + self.fields['lang'].choices = [('', 'wszystkie')] + [ + (b, b) + for b in Book.objects.values_list( + 'language', flat=True + ).distinct().order_by() + ] + self.fields['epoch'].choices = [('', 'wszystkie')] + [ + (b.slug, b.name) + for b in Tag.objects.filter(category='epoch') + ] + self.fields['genre'].choices = [('', 'wszystkie')] + [ + (b.slug, b.name) + for b in Tag.objects.filter(category='genre') + ] + + def get_querysets(self): + Tag = apps.get_model('catalogue', 'Tag') + Book = apps.get_model('catalogue', 'Book') + Picture = apps.get_model('picture', 'Picture') + Snippet = apps.get_model('catalogue', 'Snippet') + Collection = apps.get_model('catalogue', 'Collection') + qs = { + 'author': Tag.objects.filter(category='author'), + 'theme': Tag.objects.filter(category='theme'), + 'genre': Tag.objects.filter(category='genre'), + 'collection': Collection.objects.all(), + 'book': Book.objects.all(), #findable + 'snippet': Snippet.objects.all(), + 'art': Picture.objects.all(), + # art pieces + # pdbooks + # pdauthors + } + if self.cleaned_data['category']: + c = self.cleaned_data['category'] + if c != 'author': qs['author'] = Tag.objects.none() + if c != 'theme': qs['theme'] = Tag.objects.none() + if c != 'genre': qs['genre'] = Tag.objects.none() + if c != 'collection': qs['collection'] = Collection.objects.none() + if c != 'book': qs['book'] = Book.objects.none() + if c != 'quote': qs['snippet'] = Snippet.objects.none() + if c != 'art': qs['art'] = Picture.objects.none() + qs['art'] = Picture.objects.none() + + if self.cleaned_data['format']: + c = self.cleaned_data['format'] + qs['author'] = Tag.objects.none() + qs['theme'] = Tag.objects.none() + qs['genre'] = Tag.objects.none() + qs['collection'] = Collection.objects.none() + if c == 'art': + qs['book'] = Book.objects.none() + qs['snippet'] = Snippet.objects.none() + if c in ('text', 'audio', 'daisy'): + qs['art'] = Picture.objects.none() + if c == 'audio': + qs['book'] = qs['book'].filter(media__type='mp3') + qs['snippet'] = qs['snippet'].filter(book__media__type='mp3') + elif c == 'daisy': + qs['book'] = qs['book'].filter(media__type='daisy') + qs['snippet'] = qs['snippet'].filter(book__media__type='daisy') + + if self.cleaned_data['lang']: + qs['author'] = Tag.objects.none() + qs['theme'] = Tag.objects.none() + qs['genre'] = Tag.objects.none() + qs['art'] = Picture.objects.none() + qs['collection'] = Collection.objects.none() + qs['book'] = qs['book'].filter(language=self.cleaned_data['lang']) + qs['snippet'] = qs['snippet'].filter(book__language=self.cleaned_data['lang']) + + for tag_cat in ('epoch', 'genre'): + c = self.cleaned_data[tag_cat] + if c: + # FIXME nonexistent + t = Tag.objects.get(category=tag_cat, slug=c) + qs['author'] = Tag.objects.none() + qs['theme'] = Tag.objects.none() + qs['genre'] = Tag.objects.none() + qs['collection'] = Collection.objects.none() + qs['book'] = qs['book'].filter(tag_relations__tag=t) + qs['snippet'] = qs['snippet'].filter(book__tag_relations__tag=t) + qs['art'] = qs['art'].filter(tag_relations__tag=t) + + return qs + + def results(self): + qs = self.get_querysets() + query = self.cleaned_data['q'] + squery = build_search_query(query, config='polish') + query = SearchQuery(query, config='polish') + books = qs['book'].filter(title__search=query) + books = books.exclude(ancestor__in=books) + return { + 'author': qs['author'].filter(slug__search=query), + 'theme': qs['theme'].filter(slug__search=query), + 'genre': qs['genre'].filter(slug__search=query), + 'collection': qs['collection'].filter(title__search=query), + 'book': books[:100], + 'snippet': qs['snippet'].annotate( + rank=SearchRank('search_vector', squery) + ).filter(rank__gt=0).order_by('-rank').annotate( + headline=SearchHeadline( + 'text', + query, + config='polish', + start_sel='', + stop_sel='', + highlight_all=True + ) + )[:100], + 'art': qs['art'].filter(title__search=query)[:100], + } +