1 # This file is part of Wolne Lektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Wolne Lektury. See NOTICE for more information.
4 from django.conf import settings
5 from django.shortcuts import render
6 from django.views.decorators import cache
7 from django.http import HttpResponse, JsonResponse
8 from sorl.thumbnail import get_thumbnail
10 import catalogue.models
11 import infopages.models
13 from .forms import SearchFilters
17 from wolnelektury.utils import re_escape
20 query_syntax_chars = re.compile(r"[\\/*:(){}?.[\]+]")
23 def remove_query_syntax_chars(query, replace=' '):
24 return query_syntax_chars.sub(replace, query)
27 def get_hints(prefix, user=None, limit=10):
28 if not prefix: return []
31 authors = catalogue.models.Tag.objects.filter(
32 category='author', name_pl__iregex='\m' + prefix).only('name', 'id', 'slug', 'category')
37 'url': author.get_absolute_url(),
38 'img': get_thumbnail(author.photo, '72x72', crop='top').url if author.photo else '',
41 for author in authors[:limit - len(data)]
44 if user is not None and user.is_authenticated and len(data) < limit:
45 tags = social.models.UserList.objects.filter(
46 user=user, name__iregex='\m' + prefix).only('name', 'id', 'slug')
51 'url': tag.get_absolute_url(),
54 for tag in tags[:limit - len(data)]
57 tags = catalogue.models.Tag.objects.filter(
58 category__in=('theme', 'genre', 'epoch', 'kind'), name_pl__iregex='\m' + prefix).only('name', 'id', 'slug', 'category')
63 'url': tag.get_absolute_url(),
66 for tag in tags[:limit - len(data)]
69 collections = catalogue.models.Collection.objects.filter(
70 title_pl__iregex='\m' + prefix).only('title', 'slug')
74 'label': collection.title,
75 'url': collection.get_absolute_url(),
76 'slug': collection.slug,
78 for collection in collections[:limit - len(data)]
81 for b in catalogue.models.Book.objects.filter(findable=True, title__iregex='\m' + prefix)[:limit-len(data)]:
82 author_str = b.author_unicode()
83 translator = b.translator()
85 author_str += ' (tłum. ' + translator + ')'
91 'url': b.get_absolute_url(),
92 'img': get_thumbnail(b.cover_clean, '72x72').url if b.cover_clean else '',
97 infos = infopages.models.InfoPage.objects.filter(
100 title_pl__iregex='\m' + prefix).only('title', 'id', 'slug')
105 'url': info.get_absolute_url(),
108 for info in infos[:limit - len(data)]
114 def hint(request, mozhint=False, param='term'):
115 prefix = request.GET.get(param, '')
117 return JsonResponse([], safe=False)
119 prefix = re_escape(' '.join(remove_query_syntax_chars(prefix).split()))
122 limit = int(request.GET.get('max', ''))
131 user=request.user if request.user.is_authenticated else None,
143 item.get('author', '')
152 callback = request.GET.get('callback', None)
154 return HttpResponse("%s(%s);" % (callback, json.dumps(data)),
155 content_type="application/json; charset=utf-8")
157 return JsonResponse(data, safe=False)
163 filters = SearchFilters(request.GET)
165 'title': 'Wynik wyszukiwania',
166 'query': request.GET.get('q', ''),
169 if filters.is_valid():
170 ctx['results'] = filters.results()
171 for k, v in ctx['results'].items():
173 ctx['hasresults'] = True
175 return render(request, 'search/results.html', ctx)