【Flask使用】全知识md文档,4大部分60页第3篇:Flask模板使用和案例

本文的主要内容:flask视图&路由、虚拟环境安装、路由各种定义、状态保持、cookie、session、模板基本使用、过滤器&自定义过滤器、模板代码复用:宏、继承/包含、模板中特有变量和函数、Flask-WTF 表单、CSRF、数据库操作、ORM、Flask-SQLAlchemy、增删改查操作、案例、蓝图、单元测试

全套Flask笔记直接地址: 请移步这里


共 4 章,42 子模块


模板

  • 基本使用
  • 过滤器&自定义过滤器
  • 控制代码块
  • 宏、继承、包含
  • Flask 的模板中特有变量和方法
  • web表单
  • CSRF

学习目标

  • 能够写出 jinja2 中变量代码块和控制代码块的格式
  • 能够写出在模板中字典,列表的取值方式
  • 能够写出数组反转的自定义过滤器(使用1种方式即可)
  • 能够说出Flask中模板代码复用的三种方式
  • 能够使用代码实现模板继承的功能
  • 能够说出可以在模板中直接使用的 Flask 变量和函数
  • 能够使用 Flask-WTF 扩展实现注册表单
  • 能够说出 CSRF 攻击的原理

模板的使用

  • 在项目下创建 templates 文件夹,用于存放所有的模板文件,并在目录下创建一个模板html文件 temp_demo1.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
我的模板html内容
</body>
</html>
  • 设置 templates 文件夹属性以便能够在代码中有智能提示

  • 设置 html 中的模板语言,以便在 html 有智能提示

  • 创建视图函数,将该模板内容进行渲染返回
@app.route('/')
def index():return render_template('temp_demo1.html')

访问:http://127.0.0.1:5000/ 运行测试

  • 代码中传入字符串,列表,字典到模板中
@app.route('/')
def index():# 往模板中传入的数据my_str = 'Hello 黑马程序员'my_int = 10my_array = [3, 4, 2, 1, 7, 9]my_dict = {'name': 'xiaoming','age': 18}return render_template('temp_demo1.html',my_str=my_str,my_int=my_int,my_array=my_array,my_dict=my_dict)
  • 模板中代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
我的模板html内容
<br/>{{ my_str }}
<br/>{{ my_int }}
<br/>{{ my_array }}
<br/>{{ my_dict }}</body>
</html>
  • 运行效果

我的模板html内容
Hello 黑马程序员
10
[3, 4, 2, 1, 7, 9]
{‘name’: ‘xiaoming’, ‘age’: 18}Code injected by live-server

  • 相关运算,取值
<br/> my_int + 10 的和为:{{ my_int + 10 }}
<br/> my_int + my_array第0个值的和为:{{ my_int + my_array[0] }}
<br/> my_array 第0个值为:{{ my_array[0] }}
<br/> my_array 第1个值为:{{ my_array.1 }}
<br/> my_dict 中 name 的值为:{{ my_dict['name'] }}
<br/> my_dict 中 age 的值为:{{ my_dict.age }}
  • 结果
my_int + 10 的和为:20 
my_int + my_array第0个值的和为:13 
my_array 第0个值为:3 
my_array 第1个值为:4 
my_dict 中 name 的值为:xiaoming 
my_dict 中 age 的值为:18

过滤器

过滤器的本质就是函数。有时候我们不仅仅只是需要输出变量的值,我们还需要修改变量的显示,甚至格式化、运算等等,而在模板中是不能直接调用 Python 中的某些方法,那么这就用到了过滤器。

使用方式:

  • 过滤器的使用方式为:变量名 | 过滤器。
{{variable | filter_name(*args)}}
  • 如果没有任何参数传给过滤器,则可以把括号省略掉
{{variable | filter_name}}
  • 如:``,这个过滤器的作用:把变量variable 的值的首字母转换为大写,其他字母转换为小写

链式调用

在 jinja2 中,过滤器是可以支持链式调用的,示例如下:

{{ "hello world" | reverse | upper }}

常见内建过滤器

字符串操作

  • safe:禁用转义
<p>{{ '<em>hello</em>' | safe }}</p>
  • capitalize:把变量值的首字母转成大写,其余字母转小写
<p>{{ 'hello' | capitalize }}</p>
  • lower:把值转成小写
<p>{{ 'HELLO' | lower }}</p>
  • upper:把值转成大写
<p>{{ 'hello' | upper }}</p>
  • title:把值中的每个单词的首字母都转成大写
<p>{{ 'hello' | title }}</p>
  • reverse:字符串反转
<p>{{ 'olleh' | reverse }}</p>
  • format:格式化输出
<p>{{ '%s is %d' | format('name',17) }}</p>
  • striptags:渲染之前把值中所有的HTML标签都删掉
<p>{{ '<em>hello</em>' | striptags }}</p>

列表操作

  • first:取第一个元素
<p>{{ [1,2,3,4,5,6] | first }}</p>
  • last:取最后一个元素
<p>{{ [1,2,3,4,5,6] | last }}</p>
  • length:列表长度
<p>{{ [1,2,3,4,5,6] | length }}</p>
  • sum:列表求和
<p>{{ [1,2,3,4,5,6] | sum }}</p>
  • sort:列表排序
<p>{{ [6,2,3,1,5,4] | sort }}</p>

语句块过滤

{% filter upper %}#一大堆文字#
{% endfilter %}

自定义过滤器

过滤器的本质是函数。当模板内置的过滤器不能满足需求,可以自定义过滤器。自定义过滤器有两种实现方式:

  • 一种是通过Flask应用对象的 add_template_filter 方法
  • 通过装饰器来实现自定义过滤器

重要:自定义的过滤器名称如果和内置的过滤器重名,会覆盖内置的过滤器。

需求:添加列表反转的过滤器

方式一

通过调用应用程序实例的 add_template_filter 方法实现自定义过滤器。该方法第一个参数是函数名,第二个参数是自定义的过滤器名称:

def do_listreverse(li):# 通过原列表创建一个新列表temp_li = list(li)# 将新列表进行返转temp_li.reverse()return temp_liapp.add_template_filter(do_listreverse,'lireverse')
方式二

用装饰器来实现自定义过滤器。装饰器传入的参数是自定义的过滤器名称。

@app.template_filter('lireverse')
def do_listreverse(li):# 通过原列表创建一个新列表temp_li = list(li)# 将新列表进行返转temp_li.reverse()return temp_li
  • 在 html 中使用该自定义过滤器
<br/> my_array 原内容:{{ my_array }}
<br/> my_array 反转:{{ my_array | lireverse }}
  • 运行结果
my_array 原内容:[3, 4, 2, 1, 7, 9] 
my_array 反转:[9, 7, 1, 2, 4, 3]

控制代码块

控制代码块主要包含两个:

- if/else if /else / endif
- for / endfor

if语句

Jinja2 语法中的if语句跟 Python 中的 if 语句相似,后面的布尔值或返回布尔值的表达式将决定代码中的哪个流程会被执行:

{%if user.is_logged_in() %}<a href='/logout'>Logout</a>
{% else %}<a href='/login'>Login</a>
{% endif %}

过滤器可以被用在 if 语句中:

{% if comments | length > 0 %}There are {{ comments | length }} comments
{% else %}There are no comments
{% endif %}

循环

  • 我们可以在 Jinja2 中使用循环来迭代任何列表或者生成器函数
{% for post in posts %}<div><h1>{{ post.title }}</h1><p>{{ post.text | safe }}</p></div>
{% endfor %}
  • 循环和if语句可以组合使用,以模拟 Python 循环中的 continue 功能,下面这个循环将只会渲染post.text不为None的那些post:
{% for post in posts if post.text %}<div><h1>{{ post.title }}</h1><p>{{ post.text | safe }}</p></div>
{% endfor %}
  • 在一个 for 循环块中你可以访问这些特殊的变量:
变量描述
loop.index当前循环迭代的次数(从 1 开始)
loop.index0当前循环迭代的次数(从 0 开始)
loop.revindex到循环结束需要迭代的次数(从 1 开始)
loop.revindex0到循环结束需要迭代的次数(从 0 开始)
loop.first如果是第一次迭代,为 True 。
loop.last如果是最后一次迭代,为 True 。
loop.length序列中的项目数。
loop.cycle在一串序列间期取值的辅助函数。见下面示例程序。
  • 在循环内部,你可以使用一个叫做loop的特殊变量来获得关于for循环的一些信息

    • 比如:要是我们想知道当前被迭代的元素序号,并模拟Python中的enumerate函数做的事情,则可以使用loop变量的index属性,例如:
{% for post in posts%}
{{loop.index}}, {{post.title}}
{% endfor %}
  • 会输出这样的结果
1, Post title
2, Second Post
  • cycle函数会在每次循环的时候,返回其参数中的下一个元素,可以拿上面的例子来说明:
{% for post in posts%}
{{loop.cycle('odd','even')}} {{post.title}}
{% endfor %}
  • 会输出这样的结果:
odd Post Title
even Second Post

示例程序

  • 实现的效果

  • 准备数据
  # 只显示4行数据,背景颜色依次为:黄,绿,红,紫my_list = [{"id": 1,"value": "我爱工作"},{"id": 2,"value": "工作使人快乐"},{"id": 3,"value": "沉迷于工作无法自拔"},{"id": 4,"value": "日渐消瘦"},{"id": 5,"value": "以梦为马,越骑越傻"}
]
  • 模板代码
{% for item in my_list if item.id != 5 %}{% if loop.index == 1 %}<li style="background-color: orange">{{ item.value }}</li>{% elif loop.index == 2 %}<li style="background-color: green">{{ item.value }}</li>{% elif loop.index == 3 %}<li style="background-color: red">{{ item.value }}</li>{% else %}<li style="background-color: purple">{{ item.value }}</li>{% endif %}
{% endfor %}

模板代码复用

在模板中,可能会遇到以下情况:

  • 多个模板具有完全相同的顶部和底部内容
  • 多个模板中具有相同的模板代码内容,但是内容中部分值不一样
  • 多个模板中具有完全相同的 html 代码块内容

像遇到这种情况,可以使用 JinJa2 模板中的 宏、继承、包含来进行实现

对宏(macro)的理解:

  • 把它看作 Jinja2 中的一个函数,它会返回一个模板或者 HTML 字符串
  • 为了避免反复地编写同样的模板代码,出现代码冗余,可以把他们写成函数以进行重用
  • 需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免重复

使用

  • 定义宏
{% macro input(name,value='',type='text') %}<input type="{{type}}" name="{{name}}"value="{{value}}" class="form-control">
{% endmacro %}
  • 调用宏
{{ input('name' value='zs')}}
  • 这会输出
<input type="text" name="name"value="zs" class="form-control">
  • 把宏单独抽取出来,封装成html文件,其它模板中导入使用,文件名可以自定义macro.html
{% macro function(type='text', name='', value='') %}
<input type="{{type}}" name="{{name}}"
value="{{value}}" class="form-control">{% endmacro %}
  • 在其它模板文件中先导入,再调用
{% import 'macro.html' as func %}
{% func.function() %}

代码演练

  • 使用宏之前代码
<form><label>用户名:</label><input type="text" name="username"><br/><label>身份证号:</label><input type="text" name="idcard"><br/><label>密码:</label><input type="password" name="password"><br/><label>确认密码:</label><input type="password" name="password2"><br/><input type="submit" value="注册">
</form>
  • 定义宏
{#定义宏,相当于定义一个函数,在使用的时候直接调用该宏,传入不同的参数就可以了#}
{% macro input(label="", type="text", name="", value="") %}
<label>{{ label }}</label><input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}
  • 使用宏
<form>{{ input("用户名:", name="username") }}<br/>{{ input("身份证号:", name="idcard") }}<br/>{{ input("密码:", type="password", name="password") }}<br/>{{ input("确认密码:", type="password", name="password2") }}<br/>{{ input(type="submit", value="注册") }}
</form>

模板继承

模板继承是为了重用模板中的公共内容。一般Web开发中,继承主要使用在网站的顶部菜单、底部。这些内容可以定义在父模板中,子模板直接继承,而不需要重复书写。

  • 标签定义的内容
{% block top %} {% endblock %}
  • 相当于在父模板中挖个坑,当子模板继承父模板时,可以进行填充。
  • 子模板使用 extends 指令声明这个模板继承自哪个模板
  • 父模板中定义的块在子模板中被重新定义,在子模板中调用父模板的内容可以使用super()

父模板

  • base.html
{% block top %}顶部菜单
{% endblock top %}{% block content %}
{% endblock content %}{% block bottom %}底部
{% endblock bottom %}

子模板

  • extends指令声明这个模板继承自哪
{% extends 'base.html' %}
{% block content %}需要填充的内容
{% endblock content %}
  • 模板继承使用时注意点:

    • 不支持多继承
    • 为了便于阅读,在子模板中使用extends时,尽量写在模板的第一行。
    • 不能在一个模板文件中定义多个相同名字的block标签。
    • 当在页面中使用多个block标签时,建议给结束标签起个名字,当多个block嵌套时,阅读性更好。

未完待续 下一期下一章

全套笔记直接地址: 请移步这里

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/162676.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nvm切换版本之后npm用不了

原因是 nvm只给你安了对应的node没给你安装对应的node版本的npm 解决办法如下 1找到你安装的node版本号 然后去官网下载对应的版本包 这个网址就是node官网的版本列表 Index of /download/release/ 2下载后解压 把根目录这俩复制到自己的nvm安装目录下 还有那个node_modul…

Java【XML 配置文件解析】

前言 最近考试周忙得要死&#xff0c;但我却不紧不慢&#xff0c;还有三天复习时间&#xff0c;考试科目几乎都还没学呢。今天更新一个算是工具类-XML文件的解析&#xff0c;感觉还是挺有用的&#xff0c;之后可以融进自己的项目里。 XML 配置文件解析 0、导入依赖 有点像我…

企业软件定制开发的优势|app小程序网站搭建

企业软件定制开发的优势|app小程序网站搭建 企业软件定制开发是一种根据企业特定需求开发定制化软件的服务。相比于购买现成的软件产品&#xff0c;企业软件定制开发具有许多优势。 1.企业软件定制开发可以满足企业独特需求。每个企业都有自己独特的业务流程和需求&#xff0c;…

在 Redis 中使用 JSON 文档:命令行界面(CLI)和 Navicat 集成

Redis&#xff0c;因其极高的性能而闻名&#xff0c;是一款多功能的 NoSQL 数据库&#xff0c;擅长处理键值对。虽然 Redis主要用于处理简单数据结构&#xff0c;但是同样支持更多复杂的数据类型&#xff0c;如列表、集合甚至是 JSON 文件。在本文&#xff0c;我们将深入到 Red…

SAP LU04记账更改通知单创建转储单报错:L3094 记帐修改没有份存在

解决办法&#xff1a; 使用事务码LU02&#xff0c;修改过账更改状态&#xff0c;将过账更改状态改为U&#xff0c;强制关闭 1. LU04 查找记账更改通知单号 2. 事务码LU02修改状态 这个时候再用LU04去查看的时候&#xff0c;就不会再显示了

技术短视频账号矩阵seo系统--源头开发---saas工具

专注短视频账号矩阵系统源头开发---saas营销化工具&#xff0c;目前我们作为一家纯技术开发团队目前已经专注打磨开发这套系统企业版/线下版两个版本的saas营销拓客工具已经3年了&#xff0c;本套系统逻辑主要是从ai智能批量剪辑、账号矩阵全托管发布、私信触单收录、文案ai智能…

网络安全等级保护2.0国家标准

等级保护2.0标准体系主要标准如下&#xff1a;1.网络安全等级保护条例2.计算机信息系统安全保护等级划分准则3.网络安全等级保护实施指南4.网络安全等级保护定级指南5.网络安全等级保护基本要求6.网络安全等级保护设计技术要求7.网络安全等级保护测评要求8.网络安全等级保护测评…

【AGC】云存储服务端使用方法

【集成准备】 1、Python环境配置 下载Python和PyCharm并安装。 ​ 使用安装的python本身作为解释器。 ​ 安装AGC Python SDK。 ​云存储包安装完成。 ​ 2、AGC环境配置 在AGC创建项目和应用 ​ 开通云存储服务。 返回项目设置界面&#xff0c;选择Server SDK 页签…

双系统Ubuntu-22.04.3安装编译kaldi

Ubuntu物理内存要求85-100G以上&#xff0c;运行内存5-6G以上&#xff08;如果第一次安装的Ubuntu物理内存不够&#xff0c;请勿进行扩容&#xff0c;扩容易出现黑屏、蓝屏、死机的情况&#xff0c;应该卸载Ubuntu重新安装&#xff0c;在安装过程中进行内存分配&#xff1b;运行…

4.22每日一题(累次积分的计算:交换次序)

注&#xff1a;因为 是积不出的函数&#xff0c;所以先不用算&#xff0c;最后发现&#xff0c;出现dx与dy可以相互抵消&#xff0c;即可算出答案

为企业解决设备全生命周期需求,凌雄科技凸显DaaS增长价值

企业成长离不开投资&#xff0c;但毫无疑问的是&#xff0c;投资最有价值的部分在业务。相比之下&#xff0c;诸如办公设备之类的固定资产投资&#xff0c;很容易变成企业现金流的吞噬者。从购买、运维到保养、折旧、回收&#xff0c;现代企业在越来越大的办公设备规模面前&…

工具 | docker删除不使用的容器

工具 | docker删除不使用的容器 Docker 清理命令

数据库|TiDB v7.1.0 资源管控功能是如何降低运维难度和成本

目录 一、前言 二、资源管控流程图 三、资源管控 (Resource Control)测试 1&#xff09;测试集群环境 2&#xff09;Request Unit (RU) 概念 3&#xff09;资源管控参数 4&#xff09;评估实际负载所需容量 4.1 根据实际负载估算容量 方法一 or: 方法二 4.2 基于硬件…

鸿蒙原生应用/元服务开发-AGC分发如何配置签名信息

使用制作的私钥&#xff08;.p12&#xff09;文件、在AGC申请的证书文件和Profile&#xff08;.p7b&#xff09;文件&#xff0c;在DevEco Studio配置工程的签名信息&#xff0c;以构建携带发布签名信息的APP。 1.打开DevEco Studio&#xff0c;菜单选择“File > Project S…

va-Q-tec实现温度敏感产品运输过程质量控制温控无忧

摘要&#xff1a;温度敏感产品运输对供应链全流程的温度质量要求较高&#xff0c;往往需要借助特殊的温湿度监测技术产品。va-Q-tec与虹科Comet合作&#xff0c;采用虹科Comet的U系列温度记录仪&#xff0c;为集装箱运输过程提供完整的温控包装解决方案。 一、客户背景 va-Q-…

钴电解液中净化除镍除铜树脂

#钴电解液中净化除镍除铜树脂 钴是生产各种合金及电池不可或缺的原材料&#xff0c;钴资源供给主要来自于大型铜矿和镍矿的伴生开采&#xff0c;钴的主要应用领域为动力电池、3C消费电池、各种耐热合金、硬质合金、防腐合金、磁性合金及各种钴盐等。其中&#xff0c;电池领域是…

【洛谷算法题】P5714-肥胖问题【入门2分支结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5714-肥胖问题【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格式&a…

给项目快速接入链路追踪

为什么需要链路追踪&#xff1f; 我们程序员在日常工作中&#xff0c;最常做事情之一就是修bug了。如果程序只是运行在单机上&#xff0c;我们最常用的方式就是在程序上打日志&#xff0c;然后程序运行的过程中将日志输出到文件上&#xff0c;然后我们根据日志去推断程序是哪一…

redis-cluster集群

1.redis-cluster集群 redis3.0引入的分布式存储方案 集群由多个node节点组成&#xff0c;redis数据分布在这些节点之中。 在集群之中分为主节点和从节点 集群模式当中&#xff0c;主从一一对应&#xff0c;数据写入和读取与主从模式一样&#xff0c;主负责写&#xff0c;从…

网页小游戏的开发流程

网页小游戏的开发流程可以分为几个关键步骤。这只是一个一般性的流程概述&#xff0c;具体的步骤可能会根据项目的规模和要求而有所不同。此外&#xff0c;还要考虑法律和版权问题&#xff0c;确保你的游戏开发过程是合法的。下面是一个简要的概述&#xff0c;希望对大家有所帮…