Flask模板
一.Flask模板中的特殊变量和函数
用途:可以在自己的模板中访问一些Flask默认内置的函数和对象.当然,这些变量在视图中也可以使用.
1.config
可以从模板中直接访问Flask当前的config的对象:
{{ config.DEBUG}}
{{config.SECRET_KEY}}
可以写成列表形式或者:
{{[config.DEBUG, config.SECRET_KEY]}} --> 结果是列表
或者 {{ config.DEBUG, config.SECRET_KEY}}
2.request
即Flask中代表当前请求的request对象
{{request.url}} --> http://127.0.0.1:5000/
3.session
即Flask的session对象
{{session.username}} --> qia
4.g变量
在视图中设置g变量的 name 属性的值,然后在模板中直接可以取出.
{{g.name}}
5.url_for
url_for会根据传入的路由器函数名,返回该路由对应的URL,在模板中始终使用url_for()就可以安全的修改路由绑定的URL,则不必须担心模板中渲染出错的链接:
{{url_for('index'}}} --> /qi
如果我们定义的路由URL是带有参数的,则可以把它们作为关键字参数传入url_for(),Flask会把他们填充进最终生成的URL中:
{{ url_for('post', post_id=1)}} -->/post/1
6.get_flashed_messages()
这个函数会返回之前在flask中通过flask()传入的消息的列表,flash函数的作用很简单,可以把由Python字符串表示的消息加入一个消息队列中,再使用get_flashed_message()函数取出它们并消费掉:
{%for message in get_flashed_messages()%}
{{message}}
{%endfor%}
二.模板代码的复用
Flask中模板代码的复用有 3 种方式:
宏: 多个模板具有完全相同的顶部和底部内容。
继承:多个模板中具有相同的模板代码内容,但是内容中部分值不一样。
包括:(多个)模板中具有完全相同的 html 代码块内容。
1.宏
对宏(macro)的理解:
把它看作 Jinja2 中的一个函数,它会返回一个模板或者 HTML 字符串.
为了避免反复地编写同样的模板代码,出现代码冗余,可以把他们写成函数以进行重用.
需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免重复.
使用:包括 定义 和 调用 2 个步骤.
<1>定义宏
定义语法:{% macro 函数名(参数)%}
复用代码块
{% endmacro %}
使用:
{% macro input(name,value='',type='text') %}
<input type="{{type}}" name="{{name}}"
value="{{value}}" class="form-control">
{% endmacro %}
<2>调用宏
调用语法:{ % import '宏文件所在文件名' as 别名}
{{ 别名.调用宏的函数名(参数)}}
{{ 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() %}
2.模板继承
模板继承是为了重用模板中的公共内容。一般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 %}
模板继承使用时注意点:
<1>不支持多继承
<2>为了便于阅读,在子模板中使用extends时,尽量写在模板的第一行。
<3>不能在一个模板文件中定义多个相同名字的block标签。
<4>当在页面中使用多个block标签时,建议给结束标签起个名字,当多个block嵌套时,阅读性更好。
父模板和子模板的特点和功能:
父模板:抽取多个模板页面中的相同部分,一般包括顶部/中间/底部内容
子模板:继承父模板,可以完全服用父模板内容,也可以在父模板的基础上实现自己特有的页面内容.
<1>如果想要实现自己特有的页面内容,重写指定区域块,自己填充内容;
<2>如果不想要父模板中的部分内容,直接声明区域块,内容为空.
<3>如果既要实现自己的特有内容,又想使用父模板的,使用super().
<4>可以使用多继承,但是不建议使用.
3.包含
Jinja2模板中,除了宏和继承,还支持一种代码重用的功能,叫包含(Include)。它的功能是将另一个模板整个加载到当前模板中,并直接渲染。
本质:代码完全复用.
include的使用
{% include 'hello.html' %}
包含在使用时,如果包含的模板文件不存在时,程序会抛出TemplateNotFound异常,可以加上 ignore missing 关键字。如果包含的模板文件不存在,会忽略这条include语句。
include 的使用加上关键字ignore missing
{% include 'hello.html' ignore missing %}
三.控制代码块
控制代码块主要包含两个:
- if/else if /else / endif
- for / endfor
1. 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 %}
2. 循环
我们可以在 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