I am building a search engine, which needs a custom filter that displays the text surrounding a keyword, like the excerpts on Google results page. I am using regex to identify the surrounding words. Here is my code for the filter:
@register.filter(needs_autoescape=True)
@stringfilter
def show_excerpt (value, search_term, autoescape=True):
# make the keyword put into the search engine case insensitive #
keywords = re.compile(re.escape(search_term), re.IGNORECASE)
# make excerpt return 300 characters before and after keyword #
excerpt_text = '.{300}' + str(keywords) + '.{300}'
# replace the original text with excerpt #
excerpt = value.sub(excerpt_text, value)
return mark_safe(excerpt)
Code for the search engine in view.py:
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)
HTML template (it includes a custom highlight
filter that highlights the keyword put into search engine):
<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|show_excerpt:search_term }} </p>
{% endfor %}
</ul>
Error message: 'SafeText' object has no attribute 'sub'
I think I am doing .sub
wrong. I just need the excerpt to replace the entire original text (the text that I am putting a filter on). The original text starts from the beginning of the data but I just want to display the data surrounding the keyword, with my highlight
custom filter highlighting the keyword (just like on Google). Any idea?
EDIT: when I do re.sub(excerpt_text, value)
, I get the error message sub() missing 1 required positional argument: 'string'.