
本文详解 Flask 中常见的模板未找到(Template Not Found)及 {% %} 语法不被识别问题,重点讲解 base.html 继承结构、Jinja2 正确用法、目录规范与常见疏漏点,助你快速定位并修复模板渲染失败问题。
本文详解 flask 中常见的模板未找到(template not found)及 `{% %}` 语法不被识别问题,重点讲解 `base.html` 继承结构、jinja2 正确用法、目录规范与常见疏漏点,助你快速定位并修复模板渲染失败问题。
在 Flask 开发中,模板渲染失败是初学者高频踩坑场景。你遇到的 "Template not found" 错误,以及浏览器中直接显示原始 {% extends "base.html" %} 而非渲染后 HTML 的现象(即 Jinja2 标签未被解析),根本原因并非 Django 干扰或需安装 Django——Flask 自带 Jinja2 模板引擎,无需额外安装 Django;真正问题通常出在 模板路径、继承结构缺失或语法闭合错误 上。
✅ 正确的模板组织结构
Flask 要求所有 HTML 模板必须存放在项目根目录下的 templates/ 文件夹中(注意拼写为 templates,非 template 或 Templates)。若目录不存在或命名错误,render_template() 将完全无法定位文件,直接抛出 TemplateNotFound 异常。
✅ 正确结构示例:
your_flask_app/ ├── app.py ├── templates/ │ ├── base.html ← 必须存在,作为父模板 │ └── sample.html ← 继承自 base.html 的子模板
✅ base.html:模板继承的基石
base.html 是所有页面共用的骨架,定义公共结构(如导航栏、页脚)和可替换区块({% block ... %})。必须包含完整的 HTML 结构和正确的 Jinja2 闭合标签。常见错误是遗漏 {% endblock %}(如提问截图中第18行所示),这将导致 Jinja2 解析中断,后续模板无法加载。
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{% block title %}默认标题{% endblock %} - FSMA</title>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">FSMA</a>
</div>
<ul class="nav navbar-nav">
<li><a href="/show">Show</a></li>
</ul>
</div>
</nav>
<!-- 关键:定义可被子模板填充的内容区域 -->
<main class="container mt-4">
{% block body %}{% endblock %}
</main>
</body>
</html>⚠️ 注意:{% block body %} 和 {% endblock %} 必须成对出现,且不能嵌套错位。Jinja2 对缩进不敏感,但对标签闭合极其严格。
✅ 子模板:使用 {% extends %} 正确继承
子模板(如 sample.html)通过 {% extends "base.html" %} 声明继承关系,并在对应 {% block %} 中填充内容。extends 必须是文件第一行(可选空格/换行),且只能出现一次。
<!-- templates/sample.html -->
{% extends "base.html" %}
{% block title %}FSMA - 数据展示页{% endblock %}
{% block body %}
<div class="jumbotron">
<h1>Flask 动态数据展示</h1>
<p>{{ data }}</p>
<p><small>渲染时间:{{ now|datetimeformat }}</small></p>
</div>
{% endblock %}? 提示:{{ data }} 是从视图函数传入的变量;若需过滤器(如日期格式化),确保已注册(Flask 默认提供 datetimeformat 需自行实现或使用 jinja2 内置过滤器)。
✅ 视图函数:正确调用 render_template
确保路由函数中调用 render_template 时,模板名与 templates/ 下文件名完全一致(含大小写),且不带路径前缀:
# app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/show')
def simple_show_data():
data = "From Python via Flask"
return render_template("sample.html", data=data) # ✅ 正确:仅文件名
# ❌ 错误示例:render_template("templates/sample.html") 或 render_template("/sample.html")? 排查清单(快速自查)
- [ ] templates/ 目录是否存在?拼写是否为全小写?
- [ ] base.html 是否位于 templates/ 下?内容是否含完整 结构?
- [ ] 所有 {% block %} 是否均有对应的 {% endblock %}?无遗漏、无拼写错误(如 endblcok)?
- [ ] 子模板首行是否为 {% extends "base.html" %}?引号内文件名是否准确?
- [ ] render_template() 参数是否为纯文件名(如 "sample.html"),而非相对路径?
- [ ] 重启 Flask 开发服务器(Ctrl+C 后重新运行 flask run)——模板修改不会热重载,需重启生效。
✅ 总结
Flask 模板报错极少源于环境配置,绝大多数情况是结构约定未遵守:缺少 base.html、模板路径错误、extends 语法不规范或 block 标签未闭合。牢记三个核心原则:
① 模板统一置于 templates/ 目录;
② 父模板定义 block,子模板用 extends + block 填充;
③ 所有 Jinja2 标签必须严格闭合。
遵循此流程,95% 的模板渲染问题可立即解决。










