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.html looks 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:


