david / biologeek (http://biologeek.com/)

Source code of biologeek.com weblog under WTFPL.

Clone this repository (size: 252.7 KB): HTTPS / SSH
$ hg clone http://code.welldev.org/biologeek
biologeek / search / views.py
r88:858e010e7f75 108 loc 4.1 KB embed / history / annotate / raw /
# -*- coding: utf-8 -*-
import re

from django.db.models import Q
from django.http import HttpResponseRedirect
from django.views.generic.list_detail import object_list
from django.views.generic.simple import direct_to_template

from journal.models import Post
from bistrot.models import Thought
from search.forms import SearchForm

# ``normalize_query`` and ``get_query methods`` come from this blog post
# http://www.julienphalip.com/blog/2008/08/16/adding-search-django-site-snap/

def normalize_query(query_string,
                    findterms=re.compile(r'"([^"]+)"|(\S+)').findall,
                    normspace=re.compile(r'\s{2,}').sub):
    """
        Splits the query string in invidual keywords, getting rid of unecessary spaces
        and grouping quoted words together.
        Example:
        
        >>> normalize_query('  some random  words "with   quotes  " and   spaces')
        ['some', 'random', 'words', 'with quotes', 'and', 'spaces']
    
    """
    return [normspace(' ', (t[0] or t[1]).strip()) for t in findterms(query_string)] 

def get_query(query_string, search_fields):
    """
        Returns a query, that is a combination of Q objects. That combination
        aims to search keywords within a model by testing the given search fields.
    """
    query = None # Query to search for every search term        
    terms = normalize_query(query_string)
    for term in terms:
        or_query = None # Query to search for a given term in each field
        for field_name in search_fields:
            q = Q(**{"%s__icontains" % field_name: term})
            if or_query is None:
                or_query = q
            else:
                or_query = or_query | q
        if query is None:
            query = or_query
        else:
            query = query & or_query
    return query


def search_redirect(request):
    if 'search_terms' in request.REQUEST:
        form = SearchForm(request.REQUEST)
        if form.is_valid():
            search_terms = [term for term in form.cleaned_data['search_terms'].split()]
            return HttpResponseRedirect('/recherche/%s/' % ','.join(search_terms))
    return HttpResponseRedirect('/')

def searchold(request, search_terms):
    search_terms = search_terms.split(',')
    post_queryset = Post.published.all()
    for term in search_terms:
        post_queryset = post_queryset.filter(Q(title__contains = term)
                                            |Q(summary_html__contains = term)
                                            |Q(content_html__contains = term))
    thought_queryset = Thought.published.all()
    for term in search_terms:
        thought_queryset = thought_queryset.filter(Q(title__contains = term)
                                                  |Q(content_html__contains = term))
    date_list = post_queryset.dates('publication_date', 'year')[::-1]
    return direct_to_template(request, 'static/archives.html',
        {
            'post_list': post_queryset,
            'thought_list': thought_queryset,
            'date_list': date_list,
            'search': True,
            'search_terms': search_terms,
        }
    )


def search(request):
    query_string = ''
    found_entries = None
    if ('q' in request.GET) and request.GET['q'].strip():
        query_string = request.GET['q']
        
        post_query = get_query(query_string, ['title', 'summary_html', 'content_html'])
        post_queryset = Post.published.filter(post_query)
        date_list = post_queryset.dates('publication_date', 'year')[::-1]

        thought_query = get_query(query_string, ['title', 'content_html'])
        thought_queryset = Thought.published.filter(thought_query)

        return direct_to_template(request, 'static/archives.html',
            {
                'post_list': post_queryset,
                'thought_list': thought_queryset,
                'date_list': date_list,
                'search': True,
                'search_terms': normalize_query(query_string),
                'query_string': query_string,
            }
        )
    else:
        #TODO: feedback?
        return HttpResponseRedirect('/')