Highlighting

Haystack supports two different methods of highlighting. You can either use SearchQuerySet.highlight or the built-in {% highlight %} template tag, which uses the Highlighter class. Each approach has advantages and disadvantages you need to weigh when deciding which to use.

If you want portable, flexible, decently fast code, the {% highlight %} template tag (or manually using the underlying Highlighter class) is the way to go. On the other hand, if you care more about speed and will only ever be using one backend, SearchQuerySet.highlight may suit your needs better.

Use of SearchQuerySet.highlight is documented in the SearchQuerySet API documentation and the {% highlight %} tag is covered in the Template Tags documentation, so the rest of this material will cover the Highlighter implementation.

Highlighter

The Highlighter class is a pure-Python implementation included with Haystack that’s designed for flexibility. If you use the {% highlight %} template tag, you’ll be automatically using this class. You can also use it manually in your code. For example:

>>> from haystack.utils.highlighting import Highlighter

>>> my_text = 'This is a sample block that would be more meaningful in real life.'
>>> my_query = 'block meaningful'

>>> highlight = Highlighter(my_query)
>>> highlight.highlight(my_text)
u'...<span class="highlighted">block</span> that would be more <span class="highlighted">meaningful</span> in real life.'

The default implementation takes three optional kwargs: html_tag, css_class and max_length. These allow for basic customizations to the output, like so:

>>> from haystack.utils.highlighting import Highlighter

>>> my_text = 'This is a sample block that would be more meaningful in real life.'
>>> my_query = 'block meaningful'

>>> highlight = Highlighter(my_query, html_tag='div', css_class='found', max_length=35)
>>> highlight.highlight(my_text)
u'...<div class="found">block</div> that would be more <div class="found">meaningful</div>...'

Further, if this implementation doesn’t suit your needs, you can define your own custom highlighter class. As long as it implements the API you’ve just seen, it can highlight however you choose. For example:

# In ``myapp/utils.py``...
from haystack.utils.highlighting import Highlighter

class BorkHighlighter(Highlighter):
    def render_html(self, highlight_locations=None, start_offset=None, end_offset=None):
        highlighted_chunk = self.text_block[start_offset:end_offset]

        for word in self.query_words:
            highlighted_chunk = highlighted_chunk.replace(word, 'Bork!')

        return highlighted_chunk

Then set the HAYSTACK_CUSTOM_HIGHLIGHTER setting to myapp.utils.BorkHighlighter. Usage would then look like:

>>> highlight = BorkHighlighter(my_query)
>>> highlight.highlight(my_text)
u'Bork! that would be more Bork! in real life.'

Now the {% highlight %} template tag will also use this highlighter.