Search hints/javascript
[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     # import pdb; pdb.set_trace()
71     
72     tags = s.hint_tags(prefix)
73     books = s.hint_books(prefix)
74
75     # TODO DODAC TU HINTY
76
77     return JSONResponse(
78         [{'label': t.name,
79           'category': _(category_name(t.category)),
80           'id': t.id,
81           'url': t.get_absolute_url()}
82           for t in tags] + \
83           [{'label': b.title,
84             'category': _(category_name('book')),
85             'id': b.id,
86             'url': b.get_absolute_url()}
87             for b in books])
88
89
90 def foo(s, q, tag_list=None):
91     hint = s.hint()
92     try:
93         tag_list = Tag.get_tag_list(tag_list)
94         hint.tags(tag_list)
95     except:
96         tag_list = None
97
98     q = StringReader(q)
99     return (q, hint)
100
101
102 def main(request):
103     results = {}
104     JVM.attachCurrentThread()  # where to put this?
105     srch = MultiSearch()
106
107     results = None
108     query = None
109     fuzzy = False
110
111     if 'q' in request.GET:
112         tags = request.GET.get('tags', '')
113         query = request.GET['q']
114         book_id = request.GET.get('book', None)
115         book = None
116         if book_id is not None:
117             book = get_object_or_404(Book, id=book_id)
118
119         hint = srch.hint()
120         try:
121             tag_list = Tag.get_tag_list(tags)
122         except:
123             tag_list = []
124
125         if len(query) < 2:
126             return render_to_response('catalogue/search_too_short.html', {'tags': tag_list, 'prefix': query},
127                                       context_instance=RequestContext(request))
128
129         hint.tags(tag_list)
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))