Flask框架学习,更新ing,附目录
- 第壹篇----虚拟环境篇
- 第贰篇----Flask视图基础和URL
- 第叁篇----Flask之Jinja2模板
模板简介
Jinja2模板介绍和查找路径
- 模版介绍
模板是一个web开发必备的模块.因为我们在渲染一个网页的时候,并不是只渲染了一个纯文本字符串,而是需要渲染一个有富文本标签的页面.这时候我们就需要使用模板了,在flask中,配套的模板是Jinja2,Jinja2的作者也是flask的作者,这个模板非常强大,并且执行效率高.官网(但不建议去官网学习,多且乱):http://jinja.pocoo.org/ - 查找路径
(1) 在渲染模板的时候,默认会从项目根目录下的templates
目录下查找模板,可以看一下Flask源码
(2)如果不想把模板文件放在templates
目录下,那么可以在flask
初始化的时候指定template_folder
来指定模板的路径
- Flask渲染Jinja2模板
要渲染一个模板,通过render_template方法即可,比如:
- 此时如果我们想要在index.html页面中能够动态显示xxx进入的话,该怎么做呢?显然可以通过在render_template方法中添加要传递的参数,然后将参数在页面中显示出来即可,下面就详细说明一下模拟步骤
首先我们访问URL为:127.0.0.0:5000/的时候会进入到hello_world()方法内部,我们可以创建一个uname变量,作为用户名的表示,然后在render_template方法中作为形参传入
其次我们需要在index.html中,使用专门的模板语法来取出我们传递的username参数
模板传参及其技巧
- 在使用
render_template渲染模板
的时候,可以传递关键字参数(命名参数).
模板传参
页面取出参数
- 如果你的参数项过多,那么可以将所有的参数放到一个字典中,然后在传这个字典参数的时候,使用两个星号(**),将字典打散成关键字参数(也叫命名参数)
比如:
- 如果不使用上面提到的**星号打散关键字的技巧也可以是,直接使用第一种方式来将context传参也可以
模板中使用url_for
- 模板中的
url_for
跟我们视图函数中的url_for
使用起来一模一样的.也是传递视图函数的名字,也可以传递参数.使用的使用,需要在url_for
左右两边加上{{url_for('func'}}
- 案例引入:模拟一个从首页登录的案例(仅作为模拟)
代码流程介绍:运行程序后,输入127.0.0.1:5000/后会通过视图函数hello_world跳转到首页,并且点击登录按钮后,会通过视图函数login,再次跳转到登录页面
分析:可以发现在parameter.html中,采用的是将a标签中href写死的情况下进行跳转,如果以后登录的url改变了,这里就需要调整href,缺乏一定的灵活性,但是通常情况下,我们都会使用名叫login的函数作为登录的方法,换句话说URL变了,函数名不一定变,这里我们就可以使用url_for函数灵活获取URL地址
下面再介绍下,使用url_for方式进行传参的方法 - 传参方式
路径式传参
设定,在首页中点击登录按钮时,需要向login视图函数中传递name参数和age参数
查询式传参
Jinja2过滤器_基本使用
- 举例子
访问https://www.bufanbiz.com/,在说明提示时间的位置就使用到了过滤器
- 简单使用(abs表示取绝对值)
- 简单总结
1. 有时候我们想要在模版中对一些变量进行处理,那么就必须需要类似于Python中的函数一样,可以将这个值传到函数中,然后做一些操作。在模版中,过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。
基本语法:{{ variable|过滤器名字 }}
。使用管道符号|
进行组合。
Jinja2过滤器介绍
- 过滤器介绍
过滤器是通过管道符号(|)进行使用的,例如:{{ name|length }},将返回name的长度。过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。Jinja2中内置了许多过滤器,查看所有过滤器:http://jinja.pocoo.org/docs/dev/templates/#builtin-filters - 常见过滤器说明
-abs(value)
:返回一个数值的绝对值。 例如:-1|abs。
-default(value,default_value,boolean=false)
:如果当前变量没有值,则会使用参数中的值来代替。name|default(‘xiaotuo’)——如果name不存在,则会使用xiaotuo来替代.boolean=False的情况下,只有这个变量为undefined的时候才会使用default中的值,如果在变量是一些特殊值(如None,空字符串,空列表,空字典),想要依旧使用default值的话,需要设置为boolean=True或者使用or来表示—具体详解见下一小节
-escape(value)或e
:转义字符,会将<、>等符号转义成HTML中的符号。例如:content|escape或content|e。
-first(value)
:返回一个序列的第一个元素。names|first。
-format(value,*arags,**kwargs)
:格式化字符串。例如以下代码:{{ “%s” - “%s”|format(‘Hello?’,“Foo!”) }}将输出:Helloo? - Foo!
-last(value)
:返回一个序列的最后一个元素。示例:names|last。
-length(value)
:返回一个序列或者字典的长度。示例:names|length。
-join(value,d='+')
:将一个序列用d这个参数的值拼接成字符串。
-safe(value)
:如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:content_html|safe。
-int(value)
:将值转换为int类型。
-float(value)
:将值转换为float类型。
-lower(value)
:将字符串转换为小写。
-upper(value)
:将字符串转换为小写。
-replace(value,old,new)
: 替换将old替换为new的字符串。
-truncate(value,length=255,killwords=False)
:截取length长度的字符串。
-striptags(value)
:删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格。
-trim
:截取字符串前面和后面的空白字符。
-string(value)
:将变量转换成字符串。
-wordcount(s)
:计算一个长字符串中单词的个数。
Jinja2过滤器_default详解
- 案例场景:个性签名
用户设置了签名,写什么就是什么
用户没设置签名,默认给出"此人很懒,暂无任何签名" - 案例1–这里的signature是没有定义的,所以会使用默认值
- 案例2—设置signature的值
- 案例3–在案例2的情况下,如果传递的signature是一些特殊值,如None,空字符串,空字典,空列表等,想要依旧让过滤器生效,也就是说依旧采用默认值,需要在defalut添加
boolean=True
- 总结
使用方式{{ value|default('默认值') }}
。
如果value这个key
不存在,那么就会使用default
过滤器提供的默认值。
如果value这个key
存在,就不会使用default
过滤器提供的默认值。但对于value的一些特殊值(例如:None、空字符串、空列表、空字典等),想使用default
过滤器提供的默认值。,那么就必须要传递另外一个参数{{ value|default('默认值',boolean=True)}}
。 - 扩展
可以使用or
来替代default('默认值',boolean=True)
。例如:{{ signature or '此人很懒,没有留下任何说明' }}
。
以下两种写法等价
建议
使用扩展中的两种写法之一,这种情况下,如果signature未定义或者是一些特殊值会自动采用默认值,如果已经定义且非特殊值,则采用signature值
Jinja2过滤器_常用过滤器
- 常见过滤器
几个样例:
truncate截取中对于任何单个字符(如中文单个汉字,英文单个字母等等)都是按1个长度来计算的
- 关于过滤器的自动转义
Jinja2模板,默认全局 开启了自动转义功能
1.safe
过滤器:可以关闭一个字符串的自动转义。
2.escape
过滤器:对某一个字符串进行转义。
3.autoescape
jinja标签,可以对他里面的代码块关闭或开启自动转义。
- 针对默认的全局自动转义进行验证测试
在这个页面中,如果直接通过浏览器访问,那么script部分代码会被JS引擎所识别,结果是在网页中显示一个弹窗,现在尝试一下将script部分内容保存到一个视图函数中的变量中,然后传递到html再用Jinja2语法来获取
运行测试时发现,在html中显示的内容就是我们要传递的字符串,JS引擎并没有处理这部分代码,现在查看一下网页源代码
可以看到,Jinja2模板 已经将一些特殊字符进行了转义,避免了之前情况的出现,此时若我们使用safe
过滤器将该字符串关闭自动转义,再次运行时就和第一次弹窗情况一样了
Jinja2过滤器_自定义过滤器的步骤
- 只有当系统提供的过滤器不符合需求后,才须自定义过滤器,过滤器本质上就是一个函数.如果在模板中调用这个过滤器,那么就会将这个变量的值作为第一个参数传给过滤器函数,然后函数的返回值会作为这个过滤器的返回值
- 需要使用一个装饰器
@app.template_filter('过滤器名称')
- 案例:创建一个删除变量中指定内容的过滤器
Jinja2过滤器_自定义事件处理过滤器
- 代码
'''
自定义过滤器处理时间
'''
from flask import Flask,render_template
from datetime import datetime
app = Flask(__name__)
@app.template_filter('handle_time')
def handle_time(createtime):
'''
createtime距离现在的时间间隔
1.如果时间间隔小于1分钟,就显示'刚刚'
2.如果大于1分钟小于1小时,那么就显示'xx分钟前'
3.如果大于1小时小于24小时,那么就显示'xx小时前'
4.如果大于24h小于30天以内,那么就显示'xx天前'
5,否则,就显示具体创建时间
'''
if isinstance(createtime,datetime):
now=datetime.now()
timestamp = (now-createtime).total_seconds()
if timestamp<60:
return '刚刚'
elif timestamp>=60 and timestamp<60*60:
minute = timestamp/60
return "%s分钟前"%int(minute)
elif timestamp>=60*60 and timestamp<24*60*60:
hour = timestamp/(60*60)
return "%s小时前"%int(hour)
elif timestamp>=24*60*60 and timestamp<60*60*24*30:
day = timestamp/(24*60*60)
return "%s天前"%int(day)
else:
return createtime.strftime('%Y/%m/%d %H:%M')
else:
return createtime
@app.route('/')
def hello_world():
create_time=datetime(2020,6,3,18,20,22)
return render_template('time.html',create_time=create_time)
if __name__ == '__main__':
app.run()
2. 效果
控制语句_if语句详解
- 控制语句:所有的控制语句都是放在{% … %}中,并且有一个语句{% endxxx %}来进行结束,Jinja中常用的控制语句有
if/for...in...
- if语句:if语句和Python中的if类似,可以使用>,<,<=,>=,==,!=来判断,也可以通过and,or,not,()来进行逻辑合并操作
- 案例
- 强调:
if
条件判断语句必须放在{% if statement %}
中间,并且还必须有结束的标签{% endif %}
控制语句_if语句应用场景
- 场景介绍:在网页的首页中,存在一个修改个人信息的超链接,可以实现修改个人信息的功能,当点击该按钮时会向视图函数发送请求,在请求的视图函数中会查询数据库获取到该用户的个人信息,并将个人信息返回到修改信息的页面上进行显示
- 代码和结果
控制语句_for语句01
for...in...
:for循环可以遍历任何一个序列包括列表,字典,元组.并且可以进行反向遍历.- 案例
(1) 遍历列表
(2) 遍历字典
(4)遍历列表中含有字典的数据
(3) 如果序列中没有值的时候,进入else,反向遍历用过滤器reverse
- for循环中包含的其他变量,可以用来获取当前遍历的状态
loop.index
:当前迭代的索引(从1开始)
loop.index0
:当前迭代的索引(从0开始)
loop.first
:是否是第一次迭代,返回True或False
loop.last
:是否是最后一次迭代,返回True或False
loop.length
:序列的长度
- 总结
在jinja2
中的for
循环,跟python
中的for
循环基本上是一模一样的。也是for...in...
的形式。并且也可以遍历所有的序列以及迭代器。但是唯一不同的是,jinja2
中的for
循环没有break
和continue
语句。
控制语句_for循环99乘法表案例
- 实现代码
- 代码说明
采用了双层for循环,外层for循环控制的是行数,使用range(1,10)函数,可以依次取到1-9这9个数字,形成9行,在内层for循环中,控制的是每一行中列的数量,依次取出1到取出的x+1之间的数字,并进行乘法操作即可
宏的概念及基本使用
- 宏的概念
模板中的宏跟Python中的函数类似,可以传递参数,但是宏不能有返回值,可以将一些经常用到的代码片段放到宏中,然后把一些不固定的值抽取出来当成一个变量 - 基本使用
(1)定义宏(这里定义了一个名为input的宏,它含有三个参数,第一个是name,后面两个存在默认值)
(2)使用宏
(3)效果
- 注意点
(1) 在宏定义的时候,如果存在类似函数的形参,在调用宏的时候都可以不传入,那么宏的形参就会以"有默认值的以默认值,没有默认值的默认为空"为准;此外,在调用宏的时候,参数的传递时有顺序的,以上面input为例,传递的第一个参数就会赋值给name,以此类推,如果想单独仅仅给type赋值,需要单独指定,比如{{input(type=‘text’}}
(2) 宏的形参位置也是有要求的,没有默认值的参数必须要放在存在默认值的参数前面,如上面的input宏中name属性要在value和type前面
宏的导入和导入注意事项
导入
:实际开发中,不会将宏直接定义在html页面内,这样一旦定义较多宏,那么只会造成页面比较冗杂,相对的,一般都会将宏定义放在专门的文件夹中,方便进行统一管理,哪一个页面需要使用某个宏,就需要导入宏才能使用- 导入宏的两种方式
(1)from "宏文件的路径" import 宏的名字 [as xxx]
,其中as表示起别名,非必选,起别名后,在后面的使用中就必须使用别名了
{% from “macros/macros.html” import input as inp %}
(2)import "宏文件的路径" as xxx [with context]
,其中as可以理解为将整个宏文件作为某个对象,使用其中单个宏的时候,需要用指定的xxx.宏的名称
的方式
{% import “macros/macros.html” as macros with context %}
- 注意点
(1) 宏文件路径,不要以相对路径去寻找,都要以templates
作为绝对路径去找
(2) 如果想要在导入宏的时候,就把当前模板的一些参数传给宏所在的模板,那么就应该在导入宏的时候使用with context
修改视图函数,让视图函数传递一个参数到模板页面
显然传递的test参数在模板页面上就可以使用{{ test }}方式进行获取到,那么在使用下面这种导入宏的方式的前提下,想让定义宏的页面中也使用到test参数可以吗?
上图方框处,原本value值是:“提交”,但是在调用宏的时候,获取不到test参数值,而显示空值
这里就需要修改在模板页面上导入宏的方式了
include标签使用详解
- 介绍
(1) 这个标签相当于是直接将指定的模板中的代码复制粘贴到当前位置,包括被引入模板中的样式等
(2)include
标签,如果被引用的模板想要使用include标签所在的模板中的变量,直接用就可以了,不需要使用with context
,体现在下面的案例中就是:head.html可以使用首页中的变量
(3)include
的路径,也是跟import
一样,直接从templates
根目录下去找,不要以相对路径去找 - 示例
比如一个公司的网站中顶部和底部一些信息是固定的内容,在该网站上点击不同链接中如果存在重复内容,就没必要重复写这些代码,可以直接引用
set和with语句以及模板中定义变量
- set语句
在模板
中,可以使用set
语句来定义变量.示例如下:
一旦定义了这个变量,那么在后面的
代码中,都可以使用这个变量,类似于Python中的全局变量差不多 - with语句
with
语句定义的变量,只能在with
语句块中使用,超过了这个代码块,就不能再使用了,类似于Python中的局部变量
- 注意
关于定义的变量,with
语句也不一定要跟一个变量,可以定义一个空的with
语句.如果需要定义只能在指定区域内有效的变量,可以set与with组合使用.
上面这个案例中,虽然使用set定义了pname变量,但是外部被with所限制了,因此pname变量只能在with语句块的范围内使用