Make All hashtags clickable in Template with Templ

2020-04-21 06:41发布

问题:

I want to turn every hashtag in the comment textfield to url so that it will be clickable.

For example, a user submit,

s = "I can't get enough of #SO because #developers are very #supportive"

I want it to return like this in template,

I can't get enough of #SO because #developers are very #supportive

Where whole text will display and all hashtag will be clickable by embedding {hashtag}.

I tried the below templatetags code but it won't return the hashtags with the text. It will only return this,

<a href='http://example.com/tags/SO'>SO</a> 

app_extras.py

import re

register = template.Library()

@register.filter(name='hashchange')
def hashchange(value):
    vx=re.findall(r"#(\w+)", value)
    for n in vx:
        pm="<a href='http://example.com/tags/{0}'>{0}</a>".format(n)
        return pm

In the template, I did,

{{object.comment|safe|hashchange}}

What am I missing?

回答1:

You will need to use mark_safe to mark your return value as html. Keep in mind that since you are marking it as safe, you must escape it first. re.sub() is what you were looking for:

import re
from django import template
from django.utils.html import escape
from django.utils.safestring import mark_safe

register = template.Library()

def create_hashtag_link(tag):
    url = "/tags/{}/".format(tag)
    # or: url = reverse("hashtag", args=(tag,))
    return '<a href="{}">#{}</a>'.format(url, tag)


@register.filter()
def hashtag_links(value):
    return mark_safe(
        re.sub(r"#(\w+)", lambda m: create_hashtag_link(m.group(1)),
               escape(value)))

Note: We assume that value is text (unescaped), and create_hashtag_link(tag) assumes tag is a word (\w+) and does not need escaping. For creating links to other fragments of text, use format_html() instead of .format()