bigywater.tech
Flask · 52

Flask 模板搜索路径

render_template("x.html") 到底从哪里找?多个目录里有同名文件怎么办?能不能写成路径穿越?想加一个额外的模板目录怎么办?这篇建一个应用加两个蓝图,把每一步查找都打印出来。

应用优先
同名模板时应用的 templates 目录先于蓝图
拒绝
Jinja 对含 .. 的模板名与绝对路径的处理
7 个
本篇示例里 list_templates() 返回的模板名数(同名只算一个)

查找顺序

实测 · 本机执行输出
  render_template('a.html'          ) → 应用 a
  render_template('only_app.html'   ) → 只在应用里
  render_template('only_bp1.html'   ) → 只在 bp1
  render_template('only_bp2.html'   ) → 只在 bp2
  render_template('dir/x.html'      ) → 应用的 dir/x
  render_template('nope.html'       ) → TemplateNotFound: 'nope.html'

上一篇:Jinja2 Template Loader;下一篇:模板继承与 Block。蓝图自己的模板目录见Blueprint 的静态文件和模板目录。

render_template 传列表

实测 · 本机执行输出
  [nope1, only_bp2, a] → 只在 bp2 | [a, only_bp2] → 应用 a
  全都不存在 → TemplatesNotFound: none of the templates given were found: x1.html, x2.html

模板名的安全

实测 · 本机执行输出
  render_template('../secret.txt'       ) → TemplateNotFound: '../secret.txt'
  render_template('../other/x.html'     ) → TemplateNotFound: '../other/x.html'
  render_template('/etc/passwd'         ) → TemplateNotFound: '/etc/passwd'
  render_template('dir/../a.html'       ) → TemplateNotFound: 'dir/../a.html'
  render_template('dir//x.html'         ) → 应用的 dir/x
  render_template('./a.html'            ) → 应用 a
  render_template('.hidden.html'        ) → hidden
  render_template('dir\\x.html'         ) → TemplateNotFound: 'dir\\x.html'
  render_template('a.html\x00'          ) → TemplateNotFound: 'a.html\x00'

额外的模板目录

实测 · 本机执行输出
  render_template('extra_only.html') → 额外目录里的
  render_template('a.html') → 应用 a

render_template_string

实测 · 本机执行输出
  render_template_string("{{ 1 + 1 }}") → 2
  字符串模板里 include 文件模板: [只在应用里]

list_templates

实测 · 本机执行输出
   ['.hidden.html', 'a.html', 'dir/x.html', 'extra_only.html', 'only_app.html', 'only_bp1.html', 'only_bp2.html']
  被多处提供的模板名: {'a.html': ['bp1', '应用'], 'dir/x.html': ['bp1', '应用']}

分步演示

模板搜索路径
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.7 / Flask 3.1.3 / Werkzeug 3.1.9 / Jinja2 3.1.6 / SQLAlchemy 2.1.1 / gunicorn 26.2.0(都装在自己的虚拟环境里);大多数实验用 Flask 的 test_client(直接调用 WSGI 应用,不经过网络),需要真实 HTTP 时另起 gunicorn 或开发服务器(端口 9600 以上,本机 127.0.0.1);计时用 time.perf_counter,数字每次运行会有小幅抖动
    • 没有验证:Windows 路径分隔符下的模板名、符号链接指向模板目录之外时的行为、模板名大小写在不区分大小写的文件系统上的表现、PackageLoader 的查找
    京ICP备2026067502号-1京公网安备11010502063487号