第3章模板

文章目录

  • [摘要,视图函数只负责请求 → 响应,业务逻辑(数据处理)和表现逻辑(HTML 页面生成)要分开,模板(Jinja2) 用来渲染页面 → 表现逻辑移到模板中](#摘要,视图函数只负责请求 → 响应,业务逻辑(数据处理)和表现逻辑(HTML 页面生成)要分开,模板(Jinja2) 用来渲染页面 → 表现逻辑移到模板中)
  • [3.1 Jinja2模板引擎](#3.1 Jinja2模板引擎)
    • 渲染模板
      • [默认情况下,Flask在应用目录中的templates子目录里寻找模板。应用目录是哪个?创建 Flask 对象的那个 Python 文件所在目录](#默认情况下,Flask在应用目录中的templates子目录里寻找模板。应用目录是哪个?创建 Flask 对象的那个 Python 文件所在目录)
      • [render_template() 把模板和数据结合,并渲染成最终的html,返给浏览器](#render_template() 把模板和数据结合,并渲染成最终的html,返给浏览器)
    • [3.1.2 变量](#3.1.2 变量)
    • 3.1.3 控制结构
      • 条件判断(if/else)
      • 循环(for)
      • [宏(macro) --- 模板里的"函数"](#宏(macro) — 模板里的“函数”)
        • 宏的导入(import)
          • [Jinja2 宏导入从 Flask 的模板根目录 (templates) 开始找,相对路径写文件名或子目录路径即可。](#Jinja2 宏导入从 Flask 的模板根目录 (templates) 开始找,相对路径写文件名或子目录路径即可。)
      • [include --- 引入模板片段。直接把另一个模板内容原封不动插入。](#include — 引入模板片段。直接把另一个模板内容原封不动插入。)
        • [从 Flask 的模板根目录开始找(默认模板根目录)](#从 Flask 的模板根目录开始找(默认模板根目录))
        • [include ------ 引入模板片段, import ------ 引入宏(宏是函数)](#include —— 引入模板片段, import —— 引入宏(宏是函数))
      • [模板继承(extends / block / super)](#模板继承(extends / block / super))
      • [Jinja2 的重复使用代码片段方法总结,宏,include,模板继承](#Jinja2 的重复使用代码片段方法总结,宏,include,模板继承)
  • [3.2 使用Flask-Bootstrap集成Bootstrap](#3.2 使用Flask-Bootstrap集成Bootstrap)
    • [Bootstrap 是什么?网页美化工具包](#Bootstrap 是什么?网页美化工具包)
    • [Flask-Bootstrap 的作用:把bootstrp包装成jinja2可用的模板,从而实现模板继承](#Flask-Bootstrap 的作用:把bootstrp包装成jinja2可用的模板,从而实现模板继承)
    • [bootstrap = Bootstrap(app) 是Flask-Bootstrap的1种初始化方式。app是flask应用的实例](#bootstrap = Bootstrap(app) 是Flask-Bootstrap的1种初始化方式。app是flask应用的实例)
  • 3.3自定义错误界面
    • [@app.errorhandler(错误码) 就是注册一个"遇到这个错误就执行的函数"](#@app.errorhandler(错误码) 就是注册一个“遇到这个错误就执行的函数”)
      • [@app.errorhandler(404) 页面不存在](#@app.errorhandler(404) 页面不存在)
      • [@app.errorhandler(500) 服务器出错](#@app.errorhandler(500) 服务器出错)
  • 3.4 链接
    • [视图函数名和端点名不一致时,只能使用端点名。Flask 只认端点名 来生成 URL](#视图函数名和端点名不一致时,只能使用端点名。Flask 只认端点名 来生成 URL)
    • [为什么不能直接写 URL?](#为什么不能直接写 URL?)
    • [url_for() 用 端点名 生成 URL](#url_for() 用 端点名 生成 URL)
      • [为什么 浏览器内导航 → 只需要相对 URL 就够了?相对url指不带域名和端口](#为什么 浏览器内导航 → 只需要相对 URL 就够了?相对url指不带域名和端口)
      • [动态路由和 url_for()](#动态路由和 url_for())
      • 添加查询参数
  • [3.5 静态文件](#3.5 静态文件)
    • 什么叫「静态文件」?
    • [Flask 默认有一个 /static/<filename> 路由](#Flask 默认有一个 /static/<filename> 路由)
    • 默认设置下,Flask在应用目录中名为static的子目录中寻找静态文件。应用目录是哪个?创建flask对象的那个python文件所在的目录
    • [为什么要用 url_for('static', ...)?](#为什么要用 url_for('static', ...)?)
    • [url_for('static', ...) 是什么意思?static:static路由端点名filename:static 文件夹里的路径](#url_for('static', ...) 是什么意思?static:static路由端点名filename:static 文件夹里的路径)
    • [link icon指定浏览器标签页左上角的小图标](#link icon指定浏览器标签页左上角的小图标)
      • [`<link> `永远写在 `<head>` 里,使用xx类型的外部资源,它的位置在xx](#<link> 永远写在 <head> 里,使用xx类型的外部资源,它的位置在xx)
        • [href = hyper reference(超链接引用),告诉浏览器:那个资源"在哪里"](#href = hyper reference(超链接引用),告诉浏览器:那个资源“在哪里”)
          • [icon 就是我们说的 网站图标](#icon 就是我们说的 网站图标)
          • [rel="stylesheet" 页面的样式](#rel="stylesheet" 页面的样式)
          • rel="preload"提前加载一个资源
          • [为什么不是 src?src:把资源"塞进"页面,href:建立引用关系](#为什么不是 src?src:把资源“塞进”页面,href:建立引用关系)
        • [rel 决定"是什么关系"](#rel 决定“是什么关系”)
      • 为什么不是页面里的某个图标?
  • 使用Flask-Moment本地化日期和时间
    • [数据库存 UTC。服务器用 UTC。浏览器负责显示本地时间](#数据库存 UTC。服务器用 UTC。浏览器负责显示本地时间)
    • [初始化Flask-Moment。创建实例并绑定 Flask 应用](#初始化Flask-Moment。创建实例并绑定 Flask 应用)
    • [Flask-Moment(flask扩展,在模板中处理和显示时间) 和依赖](#Flask-Moment(flask扩展,在模板中处理和显示时间) 和依赖)
      • [moment.include_moment() 在 HTML 里插入加载 Moment.js 的 <script> 标签](#moment.include_moment() 在 HTML 里插入加载 Moment.js 的 <script> 标签)
      • [Flask-Moment (生成模板代码的flask扩展)和 Moment.js 的关系](#Flask-Moment (生成模板代码的flask扩展)和 Moment.js 的关系)
      • [为什么还要放在 scripts 块?](#为什么还要放在 scripts 块?)
        • [HTML 的 <script> 就是浏览器里的"程序"](#HTML 的 <script> 就是浏览器里的“程序”)
    • 例子
      • [moment() Flask-Moment 提供的模板辅助函数。把 Python 的 datetime 变成 HTML + JavaScript 代码。在浏览器中自动本地化时间](#moment() Flask-Moment 提供的模板辅助函数。把 Python 的 datetime 变成 HTML + JavaScript 代码。在浏览器中自动本地化时间)
      • [format('LLL')。'LLL' 是 Moment.js 里的格式选项](#format('LLL')。'LLL' 是 Moment.js 里的格式选项)
      • [moment(xx).fromNow() 计算 xx 相对于"现在" 是多久。显示相对时间](#moment(xx).fromNow() 计算 xx 相对于“现在” 是多久。显示相对时间)
        • [refresh=True 每隔一段时间自动刷新](#refresh=True 每隔一段时间自动刷新)
    • [Flask-Moment 假定服务器端应用处理的时间戳是"纯正的"datetime对象,且使用 UTC 表示。](#Flask-Moment 假定服务器端应用处理的时间戳是“纯正的”datetime对象,且使用 UTC 表示。)
    • 怎么让时间用不同语言显示。moment.locale

Flask Web开发:基于Python的Web应用开发实战.第2版.pdf

摘要,视图函数只负责请求 → 响应,业务逻辑(数据处理)和表现逻辑(HTML 页面生成)要分开,模板(Jinja2) 用来渲染页面 → 表现逻辑移到模板中


什么是业务逻辑 vs 表现逻辑

为什么要用模板【带占位符的文件】(Template)?


渲染(Rendering)是什么?把模板里的占位符替换成真实值

3.1 Jinja2模板引擎

Jinja2模板就是一个包含响应文本的文件

渲染模板

默认情况下,Flask在应用目录中的templates子目录里寻找模板。应用目录是哪个?创建 Flask 对象的那个 Python 文件所在目录




render_template() 把模板和数据结合,并渲染成最终的html,返给浏览器


3.1.2 变量

访问字典中的值

A value from a dictionary: {{ mydict['key'] }}.

访问列表中的值

A value from a list: {{ mylist[3] }}.

使用变量作为索引

A value from a list, with a variable index: {{ mylist[myintvar], mydict[mykey] }}.

调用对象方法

A value from an object's method: {{ myobj.somemethod() }}.

可以在模板里几乎和 Python 一样操作数据,

过滤器 把左边的值传给右边的过滤器

safe:渲染时不转义 HTML
capitalize:首字母大写,其他小写
lower:全部小写
upper:全部大写
title:每个单词首字母大写
trim:去掉首尾空格
striptags:去掉 HTML 标签
链式调用:组合多个过滤器


3.1.3 控制结构

Jinja2 提供了多种控制结构,可用来改变模板的渲染流程

条件判断(if/else)

循环(for)

宏(macro) --- 模板里的"函数"



宏的导入(import)
Jinja2 宏导入从 Flask 的模板根目录 (templates) 开始找,相对路径写文件名或子目录路径即可。


include --- 引入模板片段。直接把另一个模板内容原封不动插入。

从 Flask 的模板根目录开始找(默认模板根目录)


include ------ 引入模板片段, import ------ 引入宏(宏是函数)



不能include宏,import模板

模板继承(extends / block / super)









Jinja2 的重复使用代码片段方法总结,宏,include,模板继承

3.2 使用Flask-Bootstrap集成Bootstrap

Bootstrap 是什么?网页美化工具包




Flask-Bootstrap 的作用:把bootstrp包装成jinja2可用的模板,从而实现模板继承

bootstrap = Bootstrap(app) 是Flask-Bootstrap的1种初始化方式。app是flask应用的实例

初始化 Flask-Bootstrap 之后,就可以在应用中使用一个包含所有 Bootstrap 文件和一般结构的基模板。

怎么用 Flask-Bootstrap 给的基模板?

利用 Jinja2 的模板继承机制来扩展这个基模板




区块名 说明 位置 / 用法 举例
doc 整个 HTML 文档 最外层 <html>...</html> {% block doc %}{% endblock %} 可以覆盖整张网页
html_attribs <html> 标签的属性 比如 lang="en"class="no-js" {% block html_attribs %}lang="en"{% endblock %}
html <html> 标签中的内容 <head><body> 的全部 基模板内部用,不常直接改
head <head> 标签里的内容 放 CSS 链接、meta 标签等 {% block head %}<link rel="stylesheet"...>{% endblock %}
title <title> 标签里的内容 浏览器标签页标题 {% block title %}Flasky{% endblock %}
metas <meta> 标签集合 页面编码、视口、SEO 等 {% block metas %}<meta charset="utf-8">{% endblock %}
styles CSS 样式声明 自定义样式 {% block styles %}body {background: #f0f0f0;}{% endblock %}
body_attribs <body> 标签的属性 比如 class="home-page" {% block body_attribs %}class="home"{% endblock %}
body <body> 标签中的内容 主要内容容器 内部包含 navbarcontent,你一般不直接改
navbar 用户自定义导航栏 页面顶部菜单 {% block navbar %}...导航栏HTML...{% endblock %}
content 用户自定义页面内容 页面主体 {% block content %}<h1>Hello!</h1>{% endblock %}
scripts 文档底部的 JavaScript 放 JS 文件或脚本 {% block scripts %}<script src="..."></script>{% endblock %}

3.3自定义错误界面

@app.errorhandler(错误码) 就是注册一个"遇到这个错误就执行的函数"



@app.errorhandler(404) 页面不存在

Flask 找不到路由 → 自动生成 404 错误

如果不返回 404 状态码,浏览器会默认返回 200 OK,不符合标准

@app.errorhandler(500) 服务器出错


3.4 链接

url_for() 函数最简单的用法是以视图函数名(或者app.add_url_route()定义路由时使用的端点名)作为参数,返回对应的URL。

Flask 只认端点名 来生成 URL


视图函数名和端点名不一致时,只能使用端点名。Flask 只认端点名 来生成 URL

为什么不能直接写 URL?

url_for() 用 端点名 生成 URL


为什么 浏览器内导航 → 只需要相对 URL 就够了?相对url指不带域名和端口



动态路由和 url_for()

添加查询参数

3.5 静态文件

什么叫「静态文件」?


Flask 默认有一个 /static/ 路由

默认设置下,Flask在应用目录中名为static的子目录中寻找静态文件。应用目录是哪个?创建flask对象的那个python文件所在的目录



为什么要用 url_for('static', ...)?

url_for('static', ...) 是什么意思?static:static路由端点名filename:static 文件夹里的路径

html 复制代码
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">

兼容性写法:

shortcut icon:老浏览器 / IE

icon:现代浏览器、
<link rel="icon">(以及旧的 shortcut icon)在 HTML 标准里的含义就是页面的图标(page icon / favicon)

<link> 永远写在 <head> 里,使用xx类型的外部资源,它的位置在xx


href = hyper reference(超链接引用),告诉浏览器:那个资源"在哪里"



icon 就是我们说的 网站图标
rel="stylesheet" 页面的样式
rel="preload"提前加载一个资源
为什么不是 src?src:把资源"塞进"页面,href:建立引用关系
rel 决定"是什么关系"

为什么不是页面里的某个图标?

使用Flask-Moment本地化日期和时间

数据库存 UTC。服务器用 UTC。浏览器负责显示本地时间


初始化Flask-Moment。创建实例并绑定 Flask 应用

Flask-Moment(flask扩展,在模板中处理和显示时间) 和依赖

Flask-Moment是一个Flask扩展,能简化把Moment.js集成到Jinja2模板中

的过程。

moment.include_moment() 在 HTML 里插入加载 Moment.js 的


\site-packages\flask_bootstrap\templates\bootstrap\base.html可以看到基模板有scripts块。【点击bootstrap = Bootstrap(app)初始化的 Bootstrap类,可以看到上述位置】

Flask-Moment (生成模板代码的flask扩展)和 Moment.js 的关系

Flask-Moment(Python 扩展)只是 生成模板代码,

服务器端 Flask-Moment 只是生成 HTML/JS

Flask-Moment 不处理时间,只帮你生成浏览器需要的 HTML 和 JS,让 Moment.js 在客户端执行真正的时间处理






为什么还要放在 scripts 块?

HTML 的

例子

moment() Flask-Moment 提供的模板辅助函数。把 Python 的 datetime 变成 HTML + JavaScript 代码。在浏览器中自动本地化时间

format('LLL')。'LLL' 是 Moment.js 里的格式选项


moment(xx).fromNow() 计算 xx 相对于"现在" 是多久。显示相对时间


refresh=True 每隔一段时间自动刷新

Flask-Moment 假定服务器端应用处理的时间戳是"纯正的"datetime对象,且使用 UTC 表示。

纯正的时间戳,英文为naive time,指不包含时区的时间戳;

细致的时间戳,英文为aware time,指 包含时区的时间戳。

怎么让时间用不同语言显示。moment.locale



相关推荐
junior_Xin10 小时前
Flask框架beginning4
python·flask
junior_Xin1 天前
Flask框架beginning3
python·flask
njsgcs1 天前
windows ui窗口post 我wsl开放的flask llm端点
windows·ui·flask·post
带娃的IT创业者2 天前
专栏系列04(模块1第4篇) 《蓝图系统与中间件帝国:40+个路由模块的组织哲学》
python·中间件·flask·蓝图·blueprint·python蓝图
小小张说故事2 天前
Flask 入门指南
后端·python·flask
半熟的皮皮虾2 天前
多用户在线 Python 编辑运行和学习示例程序
开发语言·python·学习·flask
junior_Xin2 天前
Flask框架beginning2
python·flask
编码者卢布2 天前
【Azure Function】在Azure上的 Python Function 资源被扫描出包含安全漏洞
python·flask·azure
栖凤3 天前
架构选型深度分析:Spring AI vs Python(Flask + React + Milvus + MongoDB)
人工智能·python·mongodb·spring·架构·flask·milvus