Flask报TemplateNotFound错误的根本原因是默认只查找项目根目录下的templates文件夹。解决方法是在Flask()初始化时通过template_folder参数指定正确路径,且该路径相对于启动脚本位置而非项目根目录。

Flask 启动时报 TemplateNotFound 错误,但文件明明存在
根本原因通常是 Flask 没有按你预期的路径去查模板——它默认只认项目根目录下的 templates 文件夹。哪怕你把 HTML 放在 ./src/templates 或 ./app/views 里,不显式告诉 Flask,它就真看不见。
解决方式就是初始化 Flask 实例时传入 template_folder 参数:
from flask import Flask app = Flask(__name__, template_folder='./src/templates')
注意:template_folder 的路径是相对于当前 Python 脚本(即 __file__ 所在位置)的,不是相对于项目根目录或工作目录。如果你用 python run.py 启动,那路径就以 run.py 为基准。
- 支持绝对路径,比如
template_folder='/home/user/myapp/src/templates',但会牺牲可移植性 - 推荐用
os.path.join(os.path.dirname(__file__), 'src', 'templates')或pathlib.Path(__file__).parent / 'src' / 'templates'构造路径 - 如果同时用了
static_folder,它的路径逻辑和template_folder一致,但两者互不影响
用 create_app() 工厂函数时 template_folder 不生效
常见于使用应用工厂模式(比如 Flask-SQLAlchemy 或大型项目结构),错误写法是把 template_folder 写在工厂函数外部、或在 app = Flask(...) 之后才配置:
def create_app():
app = Flask(__name__) # ❌ 这里没传 template_folder
app.config.from_object(Config)
# ... register blueprints, etc.
return app
正确做法是:所有核心路径参数必须在 Flask() 构造时一次性传入,不能靠后续 app.config 补救。
-
template_folder和static_folder是Flask类的初始化参数,不是运行时可改的配置项 - 如果项目分多环境(dev/test/prod),建议把路径构造逻辑封装进工厂函数内部,避免硬编码
- 蓝图为
Blueprint实例指定template_folder(如Blueprint('auth', __name__, template_folder='auth/templates'))是另一层机制,它只影响该蓝图下的render_template()查找范围,不替代主应用的template_folder
模板路径拼接出错:为什么 render_template('admin/index.html') 找不到文件
Flask 的模板路径是“扁平化”的——render_template() 的第一个参数是纯路径字符串,它会被直接拼到 template_folder 后面,不做额外解析或规范化。
假设 template_folder='./templates',那么:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
-
render_template('index.html')→ 查找./templates/index.html -
render_template('admin/index.html')→ 查找./templates/admin/index.html(不是./templates/admin/templates/index.html) - 路径中不能出现
../,Flask 会直接拒绝并抛SecurityError
容易踩的坑:
- 误以为子目录要注册为独立模块,其实只要文件放在对应子路径下即可
- Windows 下用反斜杠
\写路径(如'admin\index.html')在某些旧版本 Flask 中可能触发异常,统一用正斜杠/ - 文件名大小写敏感:Linux/macOS 下
Index.html≠index.html,而开发时容易忽略
调试模板路径:怎么确认 Flask 到底在哪儿找文件
最直接的办法是打印 app.jinja_env.loader.searchpath,它返回一个列表,里面是 Jinja2 实际搜索的所有路径:
@app.before_first_request
def log_template_paths():
print("Template search paths:", app.jinja_env.loader.searchpath)
或者更彻底一点,在报错时加个临时断点:
try:
return render_template('xxx.html')
except Exception as e:
print("Current template paths:", app.jinja_env.loader.searchpath)
raise
这个值就是 template_folder 经过 os.path.abspath() 处理后的绝对路径,也是你真正该检查文件是否存在的地方。
别依赖 IDE 的文件树或终端 ls 输出——确保你 cd 到了启动脚本所在目录再执行 ls -R templates/,否则看到的“存在”可能是幻觉。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










