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

Django项目中Markdown转HTML后标签未渲染仅显示源码问题

问题场景

你正在开发基于Python、Django、HTML、Markdown技术栈的类维基百科站点encyclopedia,预期访问/wiki/TITLE路径时展示对应标题的百科条目内容,现有条目包含CSS、Django、Git、HTML、Python,每个条目独立存储为.md格式文件。
当前使用Python的markdown库完成Markdown到HTML的转换后,页面直接把HTML标签作为纯文本展示,标签未被浏览器解析,无法加载对应样式,相关视图代码如下:

from django.shortcuts import render
import markdown

from . import util


def index(request):
  return render(request, "encyclopedia/index.html", {
      "entries": util.list_entries()
  })

def entry(request, title):
  content = util.get_entry(title)
  if content == None:
      content = markdown.markdown(f'## {title.capitalize()}\'s page has not been 
      found')
content = markdown.markdown(content)
return render(request, f"encyclopedia/entry.html", {
    'title': title,
    'content': content
})

实际页面输出效果:
输出效果截图

问题原因

Django模板引擎默认开启自动HTML转义机制,所有通过模板变量传入的HTML标签、特殊字符都会被转义为普通文本实体,不会被浏览器解析渲染,这是框架自带的XSS攻击防护逻辑,也是你遇到标签直接明文显示的核心原因。
另外你当前的视图代码还存在两个隐性问题:

  • 代码缩进错误,content = markdown.markdown(content)和return render(...)两行没有缩进在entry函数体内,运行时会直接报错
  • 条目不存在时提前调用了一次markdown.markdown()转换内容,后续又对转换后的HTML重复做一次Markdown转换,会导致输出格式错乱
修复方案

两种方案二选一即可,优先推荐第一种,安全性更高:

  • 方案1:模板层给对应变量加安全过滤器(推荐)
    不需要额外修改视图逻辑,只需要打开templates/encyclopedia/entry.html模板文件,找到输出content变量的位置,给变量加safe过滤器,告诉Django这个变量的内容是安全的,不需要转义:
    <!-- 把原来的 {{ content }} 修改为以下写法 -->
    <div class="entry-body">
      <h1>{{ title }}</h1>
      {{ content|safe }}
    </div>
    
    记得同步修正视图代码里的缩进和重复转换问题,修正后的视图代码:
    from django.shortcuts import render
    import markdown
    
    from . import util
    
    
    def index(request):
      return render(request, "encyclopedia/index.html", {
          "entries": util.list_entries()
      })
    
    def entry(request, title):
      content = util.get_entry(title)
      if content == None:
          content = f'## {title.capitalize()}\'s page has not been found'
      content = markdown.markdown(content)
      return render(request, "encyclopedia/entry.html", {
          'title': title,
          'content': content
      })
    
  • 方案2:视图层标记转换后的内容为安全文本
    如果不想修改模板,可以在视图层导入Django的mark_safe工具,把转换完成的HTML内容标记为安全后再传给模板,修改后的视图代码:
    from django.shortcuts import render
    from django.utils.safestring import mark_safe
    import markdown
    
    from . import util
    
    
    def index(request):
      return render(request, "encyclopedia/index.html", {
          "entries": util.list_entries()
      })
    
    def entry(request, title):
      content = util.get_entry(title)
      if content == None:
          content = f'## {title.capitalize()}\'s page has not been found'
      content = mark_safe(markdown.markdown(content))
      return render(request, "encyclopedia/entry.html", {
          'title': title,
          'content': content
      })
    

注意:如果后续开放用户提交、编辑百科条目的功能,一定要对用户提交的Markdown内容做标签过滤,避免恶意脚本被注入引发XSS安全问题,不要全局关闭Django的自动转义功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:18:25