Ashley Liu
Ashley Liu

Reputation: 463

How to make custom template filter case insensitive? (Django 2.1)

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

Answers (1)

xyres
xyres

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

Related Questions