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