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 '',
42 for author in authors[:limit - len(data)]
45 if user is not None and user.is_authenticated and len(data) < limit:
46 tags = social.models.UserList.objects.filter(
47 user=user, name__iregex='\m' + prefix).only('name', 'id', 'slug')
52 'url': tag.get_absolute_url(),
55 for tag in tags[:limit - len(data)]
58 tags = catalogue.models.Tag.objects.filter(
59 category__in=('theme', 'genre', 'epoch', 'kind'), name_pl__iregex='\m' + prefix).only('name', 'id', 'slug', 'category')
64 'url': tag.get_absolute_url(),
68 for tag in tags[:limit - len(data)]
71 collections = catalogue.models.Collection.objects.filter(
72 title_pl__iregex='\m' + prefix).only('title', 'slug')
76 'label': collection.title,
77 'url': collection.get_absolute_url(),
78 'slug': collection.slug,
80 for collection in collections[:limit - len(data)]
83 for b in catalogue.models.Book.objects.filter(findable=True, title__iregex='\m' + prefix)[:limit-len(data)]:
84 author_str = b.author_unicode()
85 translator = b.translator()
87 author_str += ' (tłum. ' + translator + ')'
93 'url': b.get_absolute_url(),
94 'img': get_thumbnail(b.cover_clean, '72x72').url if b.cover_clean else '',
99 infos = infopages.models.InfoPage.objects.filter(
102 title_pl__iregex='\m' + prefix).only('title', 'id', 'slug')
107 'url': info.get_absolute_url(),
110 for info in infos[:limit - len(data)]
116 def hint(request, mozhint=False, param='term'):
117 prefix = request.GET.get(param, '')
119 return JsonResponse([], safe=False)
121 prefix = re_escape(' '.join(remove_query_syntax_chars(prefix).split()))
124 limit = int(request.GET.get('max', ''))
133 user=request.user if request.user.is_authenticated else None,
145 item.get('author', '')
154 callback = request.GET.get('callback', None)
156 return HttpResponse("%s(%s);" % (callback, json.dumps(data)),
157 content_type="application/json; charset=utf-8")
159 return JsonResponse(data, safe=False)
165 filters = SearchFilters(request.GET)
167 'title': 'Wynik wyszukiwania',
168 'query': request.GET.get('q', ''),
171 if filters.is_valid():
172 ctx['results'] = filters.results()
173 for k, v in ctx['results'].items():
175 ctx['hasresults'] = True
177 return render(request, 'search/results.html', ctx)