123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- from django.core.urlresolvers import reverse
- from django.http import Http404
- from django.shortcuts import redirect
- from django.template import RequestContext
- from django.utils import timezone
- from django.utils.translation import ugettext as _
- from haystack.query import SearchQuerySet, RelatedSearchQuerySet
- from misago.acl.exceptions import ACLError403, ACLError404
- from misago.decorators import block_crawlers
- from misago.forms import FormFields
- from misago.models import Forum, Thread, Post, User
- from misago.search import SearchException
- from misago.utils.pagination import make_pagination
- from misago.apps.errors import error403, error404
- from misago.apps.profiles.views import list as users_list
- from misago.apps.search.forms import QuickSearchForm
- class ViewBase(object):
- search_route = 'search'
- results_route = 'search_results'
- advanced_route = None
- def check_acl(self):
- pass
- def queryset(self):
- pass
- def search_form_type(self):
- return QuickSearchForm
- def render_to_response(self, template, form, context):
- tpl_dict = {
- 'form': FormFields(form),
- 'search_route': self.search_route,
- 'results_route': self.results_route,
- 'search_advanced': self.advanced_route,
- 'suggestion': None,
- 'disable_search': True,
- }
- tpl_dict.update(context)
- return self.request.theme.render_to_response('search/%s.html' % template,
- tpl_dict,
- context_instance=RequestContext(self.request))
- def __new__(cls, request, **kwargs):
- obj = super(ViewBase, cls).__new__(cls)
- return obj(request, **kwargs)
- def __call__(self, request, **kwargs):
- try:
- if request.user.is_crawler():
- raise ACLError404()
- self.check_acl()
- if not request.acl.search.can_search():
- raise ACLError403(_("You don't have permission to search community."))
- self.request = request
- return self.call(**kwargs)
- except ACLError403 as e:
- return error403(request, unicode(e))
- except ACLError404 as e:
- return error404(request, unicode(e))
- class SearchBaseView(ViewBase):
- def call(self, **kwargs):
- form_type = self.search_form_type()
- if self.request.method != "POST":
- form = self.search_form_type()(request=self.request)
- return self.render_to_response('home', form,
- {
- 'search_result': self.request.session.get(self.results_route),
- })
-
- try:
- form = self.search_form_type()(self.request.POST, request=self.request)
- if form.is_valid():
- if form.mode == 'forum':
- jump_to = Forum.objects.forum_by_name(form.target, self.request.acl)
- if jump_to:
- if jump_to.level == 1:
- return redirect(reverse('index') + ('#%s' % jump_to.slug))
- return redirect(jump_to.url)
- else:
- raise SearchException(_('Forum "%(forum)s" could not be found.') % {'forum': form.target})
- if form.mode == 'user':
- self.request.POST = self.request.POST.copy()
- self.request.POST['username'] = form.target
- return users_list(self.request)
- sqs = self.filter_queryset(SearchQuerySet().auto_query(form.cleaned_data['search_query'])).load_all()[:60]
- suggestion = SearchQuerySet().spelling_suggestion(form.cleaned_data['search_query'])
-
- if self.request.user.is_authenticated():
- self.request.user.last_search = timezone.now()
- self.request.user.save(force_update=True)
- if self.request.user.is_anonymous():
- self.request.session['last_search'] = timezone.now()
-
- if not sqs:
- raise SearchException(_("Search returned no results. Change search query and try again."), suggestion)
- if (suggestion.lower() == form.cleaned_data['search_query'].lower()
- or suggestion.lower() in form.cleaned_data['search_query'].lower()):
- suggestion = None
- if suggestion:
- new_sqs = self.filter_queryset(SearchQuerySet().auto_query(form.cleaned_data['search_query'])).load_all()[:60]
- sqs_len = len(sqs)
- new_len = len(new_sqs)
- if not new_len or new_len < sqs_len * 0.8:
- suggestion = None # We are assuming suggestion is wrong
- self.request.session[self.results_route] = {
- 'search_query': form.cleaned_data['search_query'],
- 'search_suggestion': suggestion,
- 'search_results': [p.object for p in sqs],
- }
- return redirect(reverse(self.results_route))
- else:
- if 'search_query' in form.errors:
- raise SearchException(form.errors['search_query'][0])
- raise SearchException(form.errors['__all__'][0])
- except SearchException as e:
- return self.render_to_response('error', form,
- {'message': unicode(e), 'suggestion': unicode(e.suggestion)})
- class ResultsBaseView(ViewBase):
- def call(self, **kwargs):
- result = self.request.session.get(self.results_route)
- if not result:
- form = self.search_form_type()(request=self.request)
- return self.render_to_response('error', form,
- {'message': _("No search results were found.")})
- items = result['search_results']
- items_total = len(items);
- try:
- pagination = make_pagination(kwargs.get('page', 0), items_total, 12)
- except Http404:
- return redirect(reverse(self.search_route))
- form = self.search_form_type()(request=self.request, initial={'search_query': result['search_query']})
- return self.render_to_response('results', form,
- {
- 'search_query': result['search_query'],
- 'suggestion': result['search_suggestion'],
- 'results': items[pagination['start']:pagination['stop']],
- 'items_total': items_total,
- 'pagination': pagination,
- })
|