-
Rendering search results in Django
This weekend I wrote a Django tag & filter module for rendering search results. The primary feature is truncating a body of text to show the search terms in context, just like Google shows you an excerpt. A decent text indexer will normally provide this, but most of my projects aren’t big enough to justify setting one up, so I make do with normal database queries.
Examples and documentation are on the snippet page, but here’s how I actually use it in my latest project. I have some flatpages storing documentation and other help for the web site, and a search form just for these pages. The following code can practically be dropped into any Django project using flatpages.
The view looks like this:
from django.contrib.flatpages.models import FlatPage from django.db.models import Q def help_search(request): query_string = request.GET.get('q', "") search_terms = query_string.split() results = FlatPage.objects.filter(url__startswith="/help/") if search_terms: query = Q() for term in search_terms: query &= Q(content__icontains=term) | Q(title__icontains=term) results = results.filter(query) return render_to_response("flatpages/search.html", {'query': query_string, 'terms': search_terms, 'results': results} )And the relevant portion of
flatpages/search.htmllooks like this:{% load search %} <h1>Search Results</h1> <h2> {% with results|length as result_count %} {{ result_count|default:"No" }} page{{ result_count|pluralize }} found {% if terms %}for “{{ query }}”{% endif %} {% endwith %} </h2> <ul id="results"> {% for page in results %} <li> {% searchexcerpt terms 6 as content %} {# set `content` object #} {{ page.content|striptags }} {% endsearchexcerpt %} {% highlight terms as title %} {# set `title` object #} {{ page.title }} {% endhighlight %} <h3> <a href="{{ page.get_absolute_url }}">{{ title.highlighted }}</a> {% if terms %}{% with content.hits|add:title.hits as hits %} <span class="count">{{ hits }} hit{{ hits|pluralize }}</span> {% endwith %}{% endif %} </h3> <p class="context">{{ content.excerpt|highlight:terms }}</p> </li> {% endfor %} </ul>Finally, here are some screenshots of the results:


