Merge branch 'production' into pretty
[wolnelektury.git] / apps / search / views.py
1 # -*- coding: utf-8 -*-
2
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 _
10
11 from catalogue.utils import get_random_hash
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
18
19 import enchant
20
21 dictionary = enchant.Dict('pl_PL')
22
23
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
29
30
31 def did_you_mean(query, tokens):
32     change = {}
33     for t in tokens:
34         print("%s ok? %s, sug: %s" % (t, dictionary.check(t), dictionary.suggest(t)))
35         authors = Tag.objects.filter(category='author', name__iregex=match_word_re(t))
36         if len(authors) > 0:
37             continue
38         
39         if not dictionary.check(t):
40             try:
41                 change[t] = dictionary.suggest(t)[0]
42             except IndexError:
43                 pass
44
45     if change == {}:
46         return None
47
48     for frm, to in change.items():
49         query = query.replace(frm, to)
50
51     return query
52
53
54 def hint(request):
55     prefix = request.GET.get('term', '')
56     if len(prefix) < 2:
57         return JSONResponse([])
58     JVM.attachCurrentThread()
59     s = Search()
60
61     hint = s.hint()
62     try:
63         tags = request.GET.get('tags', '')
64         hint.tags(Tag.get_tag_list(tags))
65     except:
66         pass
67
68     # tagi beda ograniczac tutaj
69     # ale tagi moga byc na ksiazce i na fragmentach
70     # jezeli tagi dot tylko ksiazki, to wazne zeby te nowe byly w tej samej ksiazce
71     # jesli zas dotycza themes, to wazne, zeby byly w tym samym fragmencie.
72
73     tags = s.hint_tags(prefix)
74     books = s.hint_books(prefix)
75
76     # TODO DODAC TU HINTY
77
78     return JSONResponse(
79         [{'label': t.name,
80           'category': _(t.category),
81           'id': t.id,
82           'url': t.get_absolute_url()}
83           for t in tags] + \
84           [{'label': b.title,
85             'category': _('book'),
86             'id': b.id,
87             'url': b.get_absolute_url()}
88             for b in books])
89
90
91 def main(request):
92     results = {}
93     JVM.attachCurrentThread()  # where to put this?
94     srch = Search()
95
96     results = None
97     query = None
98     fuzzy = False
99
100     if 'q' in request.GET:
101         tags = request.GET.get('tags', '')
102         query = request.GET['q']
103         book_id = request.GET.get('book', None)
104         book = None
105         if book_id is not None:
106             book = get_object_or_404(Book, id=book_id)
107
108         hint = srch.hint()
109         try:
110             tag_list = Tag.get_tag_list(tags)
111         except:
112             tag_list = []
113
114         if len(query) < 2:
115             return render_to_response('catalogue/search_too_short.html', {'tags': tag_list, 'prefix': query},
116                                       context_instance=RequestContext(request))
117
118         hint.tags(tag_list)
119         if book:
120             hint.books(book)
121
122         toks = StringReader(query)
123         fuzzy = 'fuzzy' in request.GET
124         if fuzzy:
125             fuzzy = 0.7
126
127         results = SearchResult.aggregate(srch.search_perfect_book(toks, fuzzy=fuzzy, hint=hint),
128                                          srch.search_book(toks, fuzzy=fuzzy, hint=hint),
129                                          srch.search_perfect_parts(toks, fuzzy=fuzzy, hint=hint),
130                                          srch.search_everywhere(toks, fuzzy=fuzzy, hint=hint))
131
132         for r in results:
133             r.process_hits()
134
135         results.sort(reverse=True)
136
137         for r in results:
138             print "-----"
139             for h in r.hits:
140                 print "- %s" % h
141
142                 # Did you mean?
143         suggestion = did_you_mean(query, srch.get_tokens(toks, field="SIMPLE"))
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,
155                                        'prefix': query,
156                                        "form": form,
157                                        'did_you_mean': suggestion},
158                 context_instance=RequestContext(request))
159
160         return render_to_response('catalogue/search_multiple_hits.html',
161                                   {'tags': tag_list,
162                                    'prefix': query,
163                                    'results': results,
164                                    'did_you_mean': suggestion},
165             context_instance=RequestContext(request))