view pylons_app/controllers/search.py @ 525:87d80c84df09

added search in specific repository added delete to my page view handled by separate controller for deleting users own repos, added fork draft
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 29 Sep 2010 22:38:54 +0200
parents 7010af6efde5
children
line wrap: on
line source

#!/usr/bin/env python
# encoding: utf-8
# search controller for pylons
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
# 
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; version 2
# of the License or (at your opinion) any later version of the license.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA  02110-1301, USA.
"""
Created on Aug 7, 2010
search controller for pylons
@author: marcink
"""
from pylons import request, response, session, tmpl_context as c, url
from pylons.controllers.util import abort, redirect
from pylons_app.lib.auth import LoginRequired
from pylons_app.lib.base import BaseController, render
from pylons_app.lib.indexers import IDX_LOCATION, SCHEMA, IDX_NAME, ResultWrapper
from webhelpers.paginate import Page
from webhelpers.util import update_params
from pylons.i18n.translation import _
from whoosh.index import open_dir, EmptyIndexError
from whoosh.qparser import QueryParser, QueryParserError
from whoosh.query import Phrase
import logging
import traceback

log = logging.getLogger(__name__)

class SearchController(BaseController):

    @LoginRequired()
    def __before__(self):
        super(SearchController, self).__before__()    

    def index(self, search_repo=None):
        c.repo_name = search_repo
        c.formated_results = []
        c.runtime = ''
        c.cur_query = request.GET.get('q', None)
        if c.cur_query:
            cur_query = c.cur_query.lower()
        
        if c.cur_query:
            p = int(request.params.get('page', 1))
            highlight_items = set()
            try:
                idx = open_dir(IDX_LOCATION, indexname=IDX_NAME)
                searcher = idx.searcher()

                qp = QueryParser("content", schema=SCHEMA)
                if c.repo_name:
                    cur_query = u'repository:%s %s' % (c.repo_name, cur_query)
                try:
                    query = qp.parse(unicode(cur_query))
                    
                    if isinstance(query, Phrase):
                        highlight_items.update(query.words)
                    else:
                        for i in query.all_terms():
                            if i[0] == 'content':
                                highlight_items.add(i[1])

                    matcher = query.matcher(searcher)
                    
                    log.debug(query)
                    log.debug(highlight_items)
                    results = searcher.search(query)
                    res_ln = len(results)
                    c.runtime = '%s results (%.3f seconds)' \
                    % (res_ln, results.runtime)
                    
                    def url_generator(**kw):
                        return update_params("?q=%s" % c.cur_query, **kw)

                    c.formated_results = Page(
                                ResultWrapper(searcher, matcher, highlight_items),
                                page=p, item_count=res_ln,
                                items_per_page=10, url=url_generator)
                           
                except QueryParserError:
                    c.runtime = _('Invalid search query. Try quoting it.')
                searcher.close()
            except (EmptyIndexError, IOError):
                log.error(traceback.format_exc())
                log.error('Empty Index data')
                c.runtime = _('There is no index to search in. Please run whoosh indexer')
                        
        # Return a rendered template
        return render('/search/search.html')