4.4 模板与静态文件:动态页面


4.4 模板与静态文件:动态页面

本节摘要:上一节用字符串拼接 HTML,代码丑、易错、没法维护。模板引擎 Jinja2 把网页搬进独立文件,Python 数据通过占位符注入——数据归 Python,页面归模板,各回各家。本节讲模板语法三件套(变量、循环、判断)、模板继承消除重复、静态文件存放样式脚本,最后把轻记账 v0.5 的界面彻底翻新。

本节的能力清单

阅读完本节,你应当能够:

  1. 解释"模板"与"渲染"的关系,说出字符串拼接的三个毛病
  2. 使用 Jinja2 的变量插值、for 循环、if 判断写出动态页面
  3. 用模板继承把页头页脚抽到基础模板
  4. 正确存放与引用 CSS、JS 静态文件
  5. 完成轻记账网页版界面的最终形态

问题:字符串拼 HTML 是条绝路

回看 4.3 的 index 视图:列表项是一行行 f-string。三个毛病会随页面复杂度指数级放大——引号嵌套地狱,加个属性就不知道哪层引号被吃掉;转义漏洞,用户在用途里输入一段 HTML 代码就能破坏页面结构,这是真实的注入攻击;职责纠缠,改个按钮颜色也要动 Python 代码。模板引擎的解法:HTML 住回自己的文件,Python 数据通过占位符"寄"进去。

图 4-4 渲染:数据与模板合体的流水线

图 4-4 渲染:数据与模板合体的流水线

模板语法:三件套

项目根目录下建 templates 文件夹(Flask 默认到此找模板),放入 index.html:

<h1>轻记账</h1> <p>本月合计 {{ total }} 元,共 {{ count }} 笔</p> {% for record in records %} <li>{{ record.item }} — {{ record.amount }} 元</li> {% endfor %} {% if total > 500 %} <p style="color: red">本月花得有点猛,注意节奏。</p> {% else %} <p>消费在预算内,继续保持。</p> {% endif %}

双花括号是变量坑位,渲染时填入真值;花括号加百分号是逻辑块,管循环与分支;自动转义默认开启——用户输入的任何 HTML 特殊字符都会被转成无害文本,字符串拼接时代的注入漏洞直接被框架没收。视图函数瘦身成三行:

from flask import render_template @app.route("/") def index(): records = ledger.all() return render_template( "index.html", records=records, total=sum(r["amount"] for r in records), count=len(records), )

render_template 找到模板、注入数据、返回成品 HTML。传参用关键字参数,模板里用同名变量——视图管造数据,模板管摆造型,边界从此清晰。

模板继承:页头页脚只写一次

每个页面都要导航栏和页脚,复制粘贴到第三页你就该意识到错了。Jinja2 的继承机制:先写一个"骨架模板",留出可替换的坑位:

<!-- templates/base.html --> <html> <head> <title>{% block title %}轻记账{% endblock %}</title> <link rel="stylesheet" href="/static/style.css"> </head> <body> <nav>轻记账 · 首页 · 统计</nav> {% block content %}{% endblock %} <footer>轻记账 v0.5</footer> </body> </html>

子模板声明继承,只填自己的坑位:

{% extends "base.html" %} {% block content %} <h1>本月支出</h1> {% for record in records %} <li>{{ record.item }} — {{ record.amount }} 元</li> {% endfor %} {% endblock %}

改导航栏只需动 base.html,全站生效——这就是"消除重复"在页面层的含义,和函数抽公共逻辑是同一个思想。

静态文件:CSS 与 JS 的家

Flask 约定项目根下的 static 文件夹存放静态资源,模板里用固定的地址前缀引用:

项目结构(目录树示意): 主脚本 —— 路由与视图 templates 文件夹 —— base.html、index.html static 文件夹 —— style.css、app.js
<link rel="stylesheet" href="/static/style.css"> <script src="/static/app.js"></script>

浏览器每访问一个页面,对每个静态文件都会再发一次独立请求(4.1 的知识:一次页面 = 一次 HTML 请求 + N 次资源请求)。所以静态文件要精简,第 6 章讲缓存与压缩时会回到这里优化加载速度。

演练:v0.5 界面翻新收尾

把 4.2 写的静态原型拆成 base.html 与 index.html,样式搬进 static 里的样式文件,视图改用 render_template。验收清单:刷新首页看到账目列表与合计;提交表单后重定向回新界面;故意在用途里输入一段 HTML 标签文字,确认页面把它原样显示而非执行——自动转义在保护你。变式一:给统计页做一个 stats.html,继承 base,按月显示支出。变式二:在模板里用循环变量 loop.index 给列表加序号,查文档找它的用法——学会查模板文档比记住每个细节更重要。

易错点清单

  • 模板文件夹放错位置:Flask 默认在应用同级找 templates,路径不对报 TemplateNotFound
  • 循环里漏 endfor:模板渲染报语法错误,行号会指向模板文件
  • 静态资源 404:引用前缀写错或文件名大小写不符,开发者工具网络面板一看便知
  • 把业务逻辑塞进模板:模板里的 if 只该做展示分支,算金额是视图的事

本节要点回顾

  • 模板 = HTML 骨架 + 占位符,render_template 负责注入数据
  • 双花括号填变量,百分号花括号跑逻辑,自动转义默认护航
  • 模板继承消灭页头页脚重复,base 骨架加 block 坑位
  • static 文件夹存样式脚本,每个资源一次独立请求
  • 视图与模板分工:数据在 Python 算,展示在模板摆

v0.5 界面齐整了。但数据还睡在 JSON 文件里,多用户一上就会打架——第 5 章,给数据一个正经的家。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U