【问题标题】:How to make custom template filter case insensitive? (Django 2.1)如何使自定义模板过滤器不区分大小写? (Django 2.1)
【发布时间】:2019-01-29 00:14:50
【问题描述】:

我的自定义模板过滤器在结果页面中突出显示放入我的搜索引擎的关键字,就像在 Google 上一样。

搜索引擎代码:

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)

自定义过滤代码:

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 模板:

<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>

结果是过滤器只突出显示与输入关键字的大小写完全匹配的文本。如果用户键入“朝鲜战争”,过滤器不会突出显示“朝鲜战争”。如何使我的过滤器不区分大小写?

【问题讨论】:

    标签: django


    【解决方案1】:

    您必须使用正则表达式来实现这一点。

    例子:

    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)
    

    【讨论】:

    • 谢谢!效果很好!请问什么是\g?抱歉,我是正则表达式的新手
    • @AshleyLiu \g 代表group。正则表达式允许您搜索组中的模式或单词。你一定在 django urls 中遇到过类似的东西 - (?P&lt;slug&gt;\w+)。括号内的模式(...) 是一个命名的捕获组,&lt;slug&gt; 是该组的名称。如果要访问slug 的匹配值,可以使用\g&lt;slug&gt;。在我的回答中,我们只是使用搜索词编译正则表达式模式。所以我们没有使用任何组。但是,正则表达式仍将默认情况下将匹配的单词保留在组号 0 中。我们可以通过调用\g&lt;0&gt;来使用匹配的单词。
    • @AshleyLiu 如果我们在模式中有多个组,例如像这样 - pattern = re.compile("(korean) (war)"),那么 "korean" 将在第 1 组中,"war" 将在第 2 组中。所以,我们'd 使用\g&lt;1&gt;\g&lt;2&gt; 来访问它们。 \g&lt;0&gt; 将同时返回它们,因为正则表达式默认将所有匹配项保留在第 0 组中。本文档通过示例更好地解释:docs.python.org/3/howto/regex.html#grouping
    • 感谢您的解释!你知道为什么这个过滤器总是在关键字第一次出现时漏掉吗?它突出显示除了第一次出现的所有关键字。例如,如果一个句子是“我的蛋糕是蛋糕店的蛋糕”,它只会突出第二个和第三个“蛋糕”,而不是第一个
    • @AshleyLiu 我现在在 python shell 中对此进行了测试,并且每次都匹配。您可以在此处查看行为:regex101.com./r/DMZ37Z/1。请参阅“替换”面板。
    猜你喜欢
    • 2013-10-24
    • 2012-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 1970-01-01
    • 2022-12-02
    • 1970-01-01
    相关资源
    最近更新 更多