merge wyszukiwania.
[wolnelektury.git] / apps / search / views.py
1 # -*- coding: utf-8 -*-
2
3 from django.shortcuts import render_to_response, get_object_or_404
4 from django.template import RequestContext
5 from django.contrib.auth.decorators import login_required
6 from django.views.decorators import cache
7 from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponsePermanentRedirect
8 from django.utils.translation import ugettext as _
9
10 from catalogue.utils import get_random_hash
11 from catalogue.models import Book, Tag, Fragment, TAG_CATEGORIES
12 from catalogue.fields import dumps
13 from catalogue.views import JSONResponse
14 from catalogue import forms
15 from search import MultiSearch, JVM, SearchResult
16 from lucene import StringReader
17 from suggest.forms import PublishingSuggestForm
18
19 import enchant
20
21 dictionary = enchant.Dict('pl_PL')
22
23
24 def did_you_mean(query, tokens):
25     change = {}
26     # sprawdzić, czy słowo nie jest aby autorem - proste szukanie termu w author!
27     for t in tokens:
28         print("%s ok? %s, sug: %s" %(t, dictionary.check(t), dictionary.suggest(t)))
29         if not dictionary.check(t):
30             try:
31                 change[t] = dictionary.suggest(t)[0]
32             except IndexError:
33                 pass
34
35     if change == {}:
36         return None
37
38     for frm, to in change.items():
39         query = query.replace(frm, to)
40
41     return query
42
43
44 def category_name(category):
45     try:
46         return filter(lambda c: c[0] == category, TAG_CATEGORIES)[0][1].encode('utf-8')
47     except IndexError:
48         raise KeyError("No category %s" % category)
49
50
51 def hint(request):
52     prefix = request.GET.get('term', '')
53     if len(prefix) < 2:
54         return JSONResponse([])
55     JVM.attachCurrentThread()
56     s = MultiSearch()
57
58     hint = s.hint()
59     try:
60         tags = request.GET.get('tags', '')
61         hint.tags(Tag.get_tag_list(tags))
62     except:
63         pass
64
65     # tagi beda ograniczac tutaj
66     # ale tagi moga byc na ksiazce i na fragmentach
67     # jezeli tagi dot tylko ksiazki, to wazne zeby te nowe byly w tej samej ksiazce
68     # jesli zas dotycza themes, to wazne, zeby byly w tym samym fragmencie.
69
70     
71     tags = s.hint_tags(prefix)
72     books = s.hint_books(prefix)
73
74     # TODO DODAC TU HINTY
75
76     return JSONResponse(
77         [{'label': t.name,
78           'category': _(category_name(t.category)),
79           'id': t.id,
80           'url': t.get_absolute_url()}
81           for t in tags] + \
82           [{'label': b.title,
83             'category': _(category_name('book')),
84             'id': b.id,
85             'url': b.get_absolute_url()}
86             for b in books])
87
88
89 def foo(s, q, tag_list=None):
90     hint = s.hint()
91     try:
92         tag_list = Tag.get_tag_list(tag_list)
93         hint.tags(tag_list)
94     except:
95         tag_list = None
96
97     q = StringReader(q)
98     return (q, hint)
99
100
101 def main(request):
102     results = {}
103     JVM.attachCurrentThread()  # where to put this?
104     srch = MultiSearch()
105
106     results = None
107     query = None
108     fuzzy = False
109
110     if 'q' in request.GET:
111         tags = request.GET.get('tags', '')
112         query = request.GET['q']
113         book_id = request.GET.get('book', None)
114         book = None
115         if book_id is not None:
116             book = get_object_or_404(Book, id=book_id)
117
118         hint = srch.hint()
119         try:
120             tag_list = Tag.get_tag_list(tags)
121         except:
122             tag_list = []
123
124         if len(query) < 2:
125             return render_to_response('catalogue/search_too_short.html', {'tags': tag_list, 'prefix': query},
126                                       context_instance=RequestContext(request))
127
128         hint.tags(tag_list)
129         if book:
130             hint.books(book)
131
132         toks = StringReader(query)
133         fuzzy = 'fuzzy' in request.GET
134         if fuzzy:
135             fuzzy = 0.7
136
137         results = SearchResult.aggregate(srch.search_perfect_book(toks, fuzzy=fuzzy, hint=hint),
138                                          srch.search_perfect_parts(toks, fuzzy=fuzzy, hint=hint),
139                                          srch.search_everywhere(toks, fuzzy=fuzzy, hint=hint))
140         results.sort(reverse=True)
141
142         for r in results:
143             print r.hits
144
145         if len(results) == 1:
146             if len(results[0].hits) == 0:
147                 return HttpResponseRedirect(results[0].book.get_absolute_url())
148             elif len(results[0].hits) == 1 and results[0].hits[0] is not None:
149                 frag = Fragment.objects.get(anchor=results[0].hits[0])
150                 return HttpResponseRedirect(frag.get_absolute_url())
151         elif len(results) == 0:
152             form = PublishingSuggestForm(initial={"books": query + ", "})
153             return render_to_response('catalogue/search_no_hits.html',
154                                       {'tags': tag_list, 'prefix': query, "pubsuggest_form": form,
155                                        'form': forms.SearchForm()},
156                 context_instance=RequestContext(request))
157
158         return render_to_response('catalogue/search_multiple_hits.html',
159                                   {'tags': tag_list, 'prefix': query,
160                                    'results': results, 'from': forms.SearchForm()},
161             context_instance=RequestContext(request))
162
163     # return render_to_response('newsearch/search.html', {'results': results,
164     #                                                     'did_you_mean': (query is not None) and
165     #                                                     did_you_mean(query, srch.get_tokens(query, field='SIMPLE')),
166     #                                                     'fuzzy': fuzzy},
167     #                           context_instance=RequestContext(request))