网站开发所需配置,js动效网站,服务器哪些端口可以做网站,wordpress百家本文的主要内容#xff1a;flask视图路由、虚拟环境安装、路由各种定义、状态保持、cookie、session、模板基本使用、过滤器自定义过滤器、模板代码复用#xff1a;宏、继承/包含、模板中特有变量和函数、Flask-WTF 表单、CSRF、数据库操作、ORM、Flask-SQLAlchemy…
本文的主要内容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 langen
headmeta charsetUTF-8titleTitle/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_strmy_str,my_intmy_int,my_arraymy_array,my_dictmy_dict)模板中代码
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/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{{ emhello/em | safe }}/pcapitalize把变量值的首字母转成大写其余字母转小写
p{{ hello | capitalize }}/plower把值转成小写
p{{ HELLO | lower }}/pupper把值转成大写
p{{ hello | upper }}/ptitle把值中的每个单词的首字母都转成大写
p{{ hello | title }}/preverse字符串反转
p{{ olleh | reverse }}/pformat格式化输出
p{{ %s is %d | format(name,17) }}/pstriptags渲染之前把值中所有的HTML标签都删掉
p{{ emhello/em | striptags }}/p列表操作
first取第一个元素
p{{ [1,2,3,4,5,6] | first }}/plast取最后一个元素
p{{ [1,2,3,4,5,6] | last }}/plength列表长度
p{{ [1,2,3,4,5,6] | length }}/psum列表求和
p{{ [1,2,3,4,5,6] | sum }}/psort列表排序
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 / endforif语句
Jinja2 语法中的if语句跟 Python 中的 if 语句相似,后面的布尔值或返回布尔值的表达式将决定代码中的哪个流程会被执行:
{%if user.is_logged_in() %}a href/logoutLogout/a
{% else %}a href/loginLogin/a
{% endif %}过滤器可以被用在 if 语句中:
{% if comments | length 0 %}There are {{ comments | length }} comments
{% else %}There are no comments
{% endif %}循环
我们可以在 Jinja2 中使用循环来迭代任何列表或者生成器函数
{% for post in posts %}divh1{{ post.title }}/h1p{{ post.text | safe }}/p/div
{% endfor %}循环和if语句可以组合使用以模拟 Python 循环中的 continue 功能下面这个循环将只会渲染post.text不为None的那些post
{% for post in posts if post.text %}divh1{{ post.title }}/h1p{{ 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 Postcycle函数会在每次循环的时候,返回其参数中的下一个元素,可以拿上面的例子来说明:
{% 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 stylebackground-color: orange{{ item.value }}/li{% elif loop.index 2 %}li stylebackground-color: green{{ item.value }}/li{% elif loop.index 3 %}li stylebackground-color: red{{ item.value }}/li{% else %}li stylebackground-color: purple{{ item.value }}/li{% endif %}
{% endfor %}模板代码复用
在模板中可能会遇到以下情况
多个模板具有完全相同的顶部和底部内容多个模板中具有相同的模板代码内容但是内容中部分值不一样多个模板中具有完全相同的 html 代码块内容
像遇到这种情况可以使用 JinJa2 模板中的 宏、继承、包含来进行实现
宏
对宏(macro)的理解
把它看作 Jinja2 中的一个函数它会返回一个模板或者 HTML 字符串为了避免反复地编写同样的模板代码出现代码冗余可以把他们写成函数以进行重用需要在多处重复使用的模板代码片段可以写入单独的文件再包含在所有模板中以避免重复
使用
定义宏
{% macro input(name,value,typetext) %}input type{{type}} name{{name}}value{{value}} classform-control
{% endmacro %}调用宏
{{ input(name valuezs)}}这会输出
input typetext namenamevaluezs classform-control把宏单独抽取出来封装成html文件其它模板中导入使用文件名可以自定义macro.html
{% macro function(typetext, name, value) %}
input type{{type}} name{{name}}
value{{value}} classform-control{% endmacro %}在其它模板文件中先导入再调用
{% import macro.html as func %}
{% func.function() %}代码演练
使用宏之前代码
formlabel用户名/labelinput typetext nameusernamebr/label身份证号/labelinput typetext nameidcardbr/label密码/labelinput typepassword namepasswordbr/label确认密码/labelinput typepassword namepassword2br/input typesubmit value注册
/form定义宏
{#定义宏相当于定义一个函数在使用的时候直接调用该宏传入不同的参数就可以了#}
{% macro input(label, typetext, name, value) %}
label{{ label }}/labelinput type{{ type }} name{{ name }} value{{ value }}
{% endmacro %}使用宏
form{{ input(用户名, nameusername) }}br/{{ input(身份证号, nameidcard) }}br/{{ input(密码, typepassword, namepassword) }}br/{{ input(确认密码, typepassword, namepassword2) }}br/{{ input(typesubmit, 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嵌套时阅读性更好。
未完待续 下一期下一章
全套笔记直接地址 请移步这里