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
相关产品推荐
相关产品推荐

