Reputation: 463
My custom template filter highlights keyword put into my search engine in the results page, just like on Google.
Search engine code:
def query_search(request):
articles = cross_currents.objects.all()
search_term = ''
if 'keyword' in request.GET:
search_term = request.GET['keyword']
articles = articles.annotate(similarity=Greatest(TrigramSimilarity('Title', search_term), TrigramSimilarity('Content', search_term))).filter(similarity__gte=0.03).order_by('-similarity')
context = {'articles': articles, 'search_term': search_term}
return render(request, 'query_search.html', context)
Custom filter code:
register = template.Library()
@register.filter(needs_autoescape=True)
@stringfilter
def highlight(value, search_term, autoescape=True):
return mark_safe(value.replace(search_term, "<span class='highlight'>%s</span>" % search_term))
HTML template:
<ul>
{% for article in articles %}
<li><a href="{% url 'search:article_detail' article.ArticleID %}">{{ article|highlight:search_term }}</a></li>
<p> {{ article.Content|highlight:search_term|truncatewords:2000 }} </p>
{% endfor %}
</ul>
The result is that the filter only highlights the text that exactly matches the case of the input keyword. If the user types "korean war", the filter will not highlight "Korean War". How can I make my filter case insensitive?
Upvotes: 1
Views: 294
Reputation: 21799
You'll have to use regular expression to achieve this.
Example:
import re
def highlight(value, search_term, autoescape=True):
# first compile the regex pattern using the search_term
pattern = re.compile(re.escape(search_term), re.IGNORECASE)
# now replace
new_value = pattern.sub('<span class="highlight">\g<0></span>', value)
return mark_safe(new_value)
Upvotes: 2