1 # -*- coding: utf-8 -*-
3 from django.conf import settings
4 from django.shortcuts import render_to_response, get_object_or_404
5 from django.template import RequestContext
6 from django.contrib.auth.decorators import login_required
7 from django.views.decorators import cache
8 from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponsePermanentRedirect
9 from django.utils.translation import ugettext as _
11 from catalogue.utils import split_tags
12 from catalogue.models import Book, Tag, Fragment
13 from catalogue.fields import dumps
14 from catalogue.views import JSONResponse
15 from search import Search, JVM, SearchResult
16 from lucene import StringReader
17 from suggest.forms import PublishingSuggestForm
21 dictionary = enchant.Dict('pl_PL')
24 def match_word_re(word):
25 if 'sqlite' in settings.DATABASES['default']['ENGINE']:
26 return r"\b%s\b" % word
27 elif 'mysql' in settings.DATABASES['default']['ENGINE']:
28 return "[[:<:]]%s[[:>:]]" % word
31 def did_you_mean(query, tokens):
34 authors = Tag.objects.filter(category='author', name__iregex=match_word_re(t))
38 if not dictionary.check(t):
40 change_to = dictionary.suggest(t)[0].lower()
41 if change_to != t.lower():
49 for frm, to in change.items():
50 query = query.replace(frm, to)
56 prefix = request.GET.get('term', '')
58 return JSONResponse([])
59 JVM.attachCurrentThread()
64 tags = request.GET.get('tags', '')
65 hint.tags(Tag.get_tag_list(tags))
69 # tagi beda ograniczac tutaj
70 # ale tagi moga byc na ksiazce i na fragmentach
71 # jezeli tagi dot tylko ksiazki, to wazne zeby te nowe byly w tej samej ksiazce
72 # jesli zas dotycza themes, to wazne, zeby byly w tym samym fragmencie.
74 tags = s.hint_tags(prefix, pdcounter=True)
75 books = s.hint_books(prefix)
81 'category': _(t.category),
83 'url': t.get_absolute_url()}
86 'category': _('book'),
88 'url': b.get_absolute_url()}
94 JVM.attachCurrentThread() # where to put this?
101 if 'q' in request.GET:
102 # tags = request.GET.get('tags', '')
103 query = request.GET['q']
104 # book_id = request.GET.get('book', None)
106 # if book_id is not None:
107 # book = get_object_or_404(Book, id=book_id)
111 # tag_list = Tag.get_tag_list(tags)
116 return render_to_response('catalogue/search_too_short.html', {'prefix': query},
117 context_instance=RequestContext(request))
119 # hint.tags(tag_list)
122 tags = srch.hint_tags(query, pdcounter=True, prefix=False, fuzzy=fuzzy)
123 tags = split_tags(tags)
125 toks = StringReader(query)
128 author_results = srch.search_phrase(toks, 'authors', fuzzy=fuzzy, tokens_cache=tokens_cache)
129 title_results = srch.search_phrase(toks, 'title', fuzzy=fuzzy, tokens_cache=tokens_cache)
131 # Boost main author/title results with mixed search, and save some of its results for end of list.
132 # boost author, title results
133 author_title_mixed = srch.search_some(toks, ['authors', 'title', 'tags'], fuzzy=fuzzy, tokens_cache=tokens_cache)
134 author_title_rest = []
135 for b in author_title_mixed:
136 bks = filter(lambda ba: ba.book_id == b.book_id, author_results + title_results)
140 author_title_rest.append(b)
142 # Do a phrase search but a term search as well - this can give us better snippets then search_everywhere,
143 # Because the query is using only one field.
144 text_phrase = SearchResult.aggregate(
145 srch.search_phrase(toks, 'content', fuzzy=fuzzy, tokens_cache=tokens_cache, snippets=True, book=False, slop=4),
146 srch.search_some(toks, ['content'], tokens_cache=tokens_cache, snippets=True, book=False))
148 everywhere = srch.search_everywhere(toks, fuzzy=fuzzy, tokens_cache=tokens_cache)
150 def already_found(results):
153 if e.book_id == r.book_id:
159 f = already_found(author_results + title_results + text_phrase)
160 everywhere = filter(lambda x: not f(x), everywhere)
162 author_results = SearchResult.aggregate(author_results)
163 title_results = SearchResult.aggregate(title_results)
165 everywhere = SearchResult.aggregate(everywhere, author_title_rest)
167 for res in [author_results, title_results, text_phrase, everywhere]:
168 res.sort(reverse=True)
171 h['snippets'] = map(lambda s:
172 re.subn(r"(^[ \t\n]+|[ \t\n]+$)", u"",
173 re.subn(r"[ \t\n]*\n[ \t\n]*", u"\n", s)[0])[0], h['snippets'])
175 suggestion = did_you_mean(query, srch.get_tokens(toks, field="SIMPLE"))
176 print "dym? %s" % repr(suggestion).encode('utf-8')
178 results = author_results + title_results + text_phrase + everywhere
179 results.sort(reverse=True)
181 if len(results) == 1:
182 fragment_hits = filter(lambda h: 'fragment' in h, results[0].hits)
183 if len(fragment_hits) == 1:
184 #anchor = fragment_hits[0]['fragment']
185 #frag = Fragment.objects.get(anchor=anchor)
186 return HttpResponseRedirect(fragment_hits[0]['fragment'].get_absolute_url())
187 return HttpResponseRedirect(results[0].book.get_absolute_url())
188 elif len(results) == 0:
189 form = PublishingSuggestForm(initial={"books": query + ", "})
190 return render_to_response('catalogue/search_no_hits.html',
194 'did_you_mean': suggestion},
195 context_instance=RequestContext(request))
197 print "TAGS: %s" % tags
198 return render_to_response('catalogue/search_multiple_hits.html',
201 'results': { 'author': author_results,
202 'title': title_results,
203 'content': text_phrase,
204 'other': everywhere},
205 'did_you_mean': suggestion},
206 context_instance=RequestContext(request))