You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django如何识别字符串中话题标签并替换为包裹的<a>标签

实现方案

推荐方案:使用re.sub回调函数一次性处理

该方案不需要提前收集待替换标签,在替换的回调函数中同步完成合法性校验、分类创建逻辑,效率更高,也能避免多次替换带来的匹配冲突问题。

def clean_content(self):
    content = self.cleaned_data.get('content')
    content = profanity.censor(content) # 不相关代码

    def replace_hashtag(match):
        hsh = match.group(1)
        # 长度不符合要求直接返回原始内容
        if len(hsh) >= 80:
            return match.group(0)
        # 校验分类是否存在,不存在则新建
        if not Category.objects.filter(name__iexact=hsh).exists():
            # 此处保留你原有的新建分类逻辑
            pass
        # 返回拼接好的链接标签
        return f'<a href="http://127.0.0.1:8000/c/{hsh}">#{hsh}</a>'
    
    # 执行全局替换
    content = re.sub(r"#(\w+)", replace_hashtag, content)
    return content

兼容现有逻辑的替换方案

如果你不想修改已经写好的标签校验逻辑,可以直接在现有代码后新增如下替换逻辑:

def clean_content(self):
    content = self.cleaned_data.get('content')
    content = profanity.censor(content) # 不相关代码
    arr = re.findall(r"#(\w+)", content)
    replace_ar = []
    for hsh in arr:
        if len(hsh) < 80:
            if Category.objects.filter(name__iexact=hsh):
                # 已有分类,添加到分类列表,不相关代码
                replace_ar.append(hsh)
            else:
                # 新建分类后添加到分类列表,不相关代码
                replace_ar.append(hsh)
        else:
            # 话题标签过长,不处理
            pass
    
    # 新增替换逻辑
    for hsh in replace_ar:
        # 用正则匹配完整标签,避免部分匹配错误
        content = re.sub(rf'#({re.escape(hsh)})\b', rf'<a href="http://127.0.0.1:8000/c/\1">#\1</a>', content)
    
    return content

注意事项

  • 替换时加入了\b单词边界符,避免标签内容被部分匹配,例如不会误替换#summerday中的#summer片段
  • 若你的站点需要支持中文话题标签,可将正则匹配规则中的\w替换为[^\s#]+,适配中文、英文、emoji等多种标签内容
  • 如果你使用Django模板渲染处理后的内容,需要在模板变量后添加|safe过滤器,避免HTML链接被自动转义为纯文本

内容的提问来源于stack exchange,提问作者Dheirya Tyagi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 16:09:02