Flask模版 jinjan2
使用模版
在渲染模版时,默认会从项目根目录下的templates文件夹下查找 模版文件
可以在 flask 初始化的时候通过template_folder 指定模版目录
模版参数
使用render_template时,可以通过传递关键字参数,在模版中直接使用{{ key }}的方式使用
如果参数过多,可以将参数放在 字典中,然后通过render_template(template_name_or_list, **context)的方式在模版中调用
模版中url_for
通 后台视图函数中的使用方式,在模版中用{{ url_for() }}
过滤器
过滤器 通过管道符 (|) 使用的,例如:{{name | length}}将返回 name 变量的长度。
过滤器相当于一个函数。
jinjan2中内置了许多过滤器
基本语法:{{ 变量名 | 过滤器名称 }}
常用过滤器
default()
例如:默认个性签名
个性签名:{{title | default("此人很懒,没有留下签名...",true)}}
或者
个性签名:{{title or "此人很懒,没有留下签名..."}}
自动转义过滤器
safe过滤器, 可以关闭一个字符串的转义
escape过滤器 ,对某一个字符串进行转义
autoescape标签,可以对在它里面的代码块关闭或开启自动转义
{% autoescape off/on %}
个性签名:{{title | escape}}
{% endautoescape %}
length(value)
first(value)
last(value)
join(value,d=u'')
int(value) / float(value) / string(value)
upper(value) / lower(value)
replace(value,old,new)
truncate(s, length=255, killwords=False, end='...', leeway=None) 截断字符
striptags(value) 过滤 SGML/XML 标签
等等
自定义过滤器
过滤器本质上就是一个函数,如果调用这个过滤器,就会将模版中的变量当作这个函数的第一个参数,函数的返回结果就是 过滤之后的结果,实现自定义过滤器的步骤:
在 python 文件中 写好过滤器函数
使用装饰器 template_filter(name)装饰该过滤器函数,将该函数添加到全局
@app.template_filter(name='cut_hello') # name 就作为自定义过滤器的名称,在模版中使用
def cut_hello(value):
value = value.replace('hello', '')
return value
案例:自定义一个时间过滤器,用来统计文章发布的时间
# 自定义的创建时间的过滤器
@app.template_filter('cacl_time')
def cacl_create_time(time):
"""
计算距离现在的时间间隔
:param time: 发表时的时间
:return: 发表时间距离现在的时间
如果时间小于一分钟,就显示'刚刚'
如果时间大于1分钟小于60分钟 显示 'xx分钟前'
如果时间大于1小时小于24小时 显示 'xx小时前'
如果时间大于1天小于30天 显示 'xx天前'
否则显示 'x年x月x日'
"""
if isinstance(time, datetime):
now = datetime.now()
t = (now - time).total_seconds() # 获取间隔的秒数
print(t)
if t <= 60:
return '刚刚'
elif 60 < t <= 60 * 60:
return "{}分钟前".format(int(t / 60))
elif 60 * 60 < t <= 3600 * 24:
return "{}小前".format(int(t / (60 * 60)))
elif 60 * 60 * 24 < t <= 60 * 60 * 24 * 30:
return "{}天前".format(int(t / (3600 * 24)))
elif 60 * 60 * 24 * 30 < t <= 60 * 60 * 24 * 30 * 12:
return "{}月前".format(int(t / (60 * 60 * 24 * 30)))
else:
return time.strftime('%Y/%m/%d')
return time
流程控制语句
所有的流程控制语句都必须放在 {% %}中,并且还有 end 语句
if条件语句
格式:
{% if xxx %}
语句块
{% else %}
语句块
{% endif %}
与python类似,可以使用 and,or,not,() 等逻辑进行操作。
for 、for in 循环语句
格式:
{% for 变量 in 可迭代对象 %}
代码块
{% endfor %}
使用方式和 python 一样,并且 jinjan2中的 for 循环包括以下变量,可以用来获取当前的遍历状态:
变量
描述
loop.index
当前迭代的索引(从 1 开始)
loop.index0
当前迭代的索引(从 0 开始)
loop.first
是否是第一次迭代,返回 True 或者 False
loop.last
是否是最后一次迭代,返回 True 或者 False
loop.length
序列的长度
注意 不可使用 continue 和 break 来控制循环的执行
可以和 else 一起使用
宏 与 inclue语句
宏
模版中的宏跟python中的函数类似,可以传递参数,但是不能有返回值,可以将一些经常使用到的代码片段放到宏中,然后把一些不固定的值抽出来当成一个变量,以下通过一个例子来说明:
定义宏
{% macro input(name, value='',type='text') %}
{% endmacro %}
使用宏
用户名:{{ input('username') }}
密码:{{ input(name='password',type='password') }}
{{ input(name='', value="提交", type='submit') }}
导入宏
在开发中,常常把一些常用的宏单独放在一个文件中,在需要的时候再倒入。
import 语句用法跟 python 中类似,可以直接使用 import ... as ...
也可以使用from ... import ... [ as ...],
例如在macros.html文件夹下,有 宏 input,那么导入它的形式可以如下:
{# 注意:from 之后跟 文件名字符串 ,默认从项目模版文件路径下算起 #}
{% from 'macros.html' import input %}
或者
{% import 'macros.html' as maros %}
这种方式,使用需要用 maros.xxx 格式。
注意:
宏文件的路径都是从模版路径算起的。
在导入宏时,如果 需要红的定义需要使用后台传递的参数,
那么在导入宏的时候可以 添加 with context
inclue语句
inclue语句是可以把加载一些 公用的模版,
直接把 文件 粘贴到 导入的地方
使用方式 include 模版文件路径(从项目指定的模版文件算起)
如果需要使用父模板中的变量,直接使用,不需要 添加 with context
set、with 语句
在模版中, 可以使用set语句来定义变量。示例如下:
{% set username = 'ck' %}
一旦定义了这个变量,那么在后面的代码中,都可以使用这个变量,
类似于 python 中的变量定义。
如果需要限制范围,可以用with语句,如下:
{% with username = 'ck' %}
用户名:{{ username }}
{% endwith %}
或者
{% with %}
{% set username = 'ck' %}
用户名:{{ username }}
{% endwith %}
范围在 with与endwith之间
加载 静态文件
在模版文件中使用 url_for('static',filename='文件的路径')
例如,加载一个css文件
{{ url_for('static',filename='css/index.css') }}">
注意:filename是从 项目静态文件夹算起的
模版继承
为什么要使用模版继承
模版继承可以把一些公用的代码单独抽取出来放到一个父模板中,以后子模板只要继承就可以使用了。这样可以减少重复性的代码。
模版继承的语法
使用extends语句,来指明继承的父模板。父模板的路径也是templates下的绝对路径,示例代码如下:
{% extends 'base.html'%}
block语法
一般在父模板中,定义一些公用的代码。子模板中可能更具不同的需求实现不同的功能
这时候父模板可以提供一个接口,让子模板实现,从而实现不同的业务需求。
在父模板中:
{% block block_name %}
{% endblock %}
在子模板中:
{% block block_name %}
子模板中代码的实现
{% endblock %}
调用父模板中 block 的代码
默认情况下,子模板实现了父模板中的代码,那么子模板就会覆盖掉父模板中的代码,
如果还不需要覆盖父模板中的代码,那么可以使用 {{ super() }}来调用父模板中的代码
,示例如下:
父模板中:
{% block content %}
这是父模板中 block中的代码
{% endblock %}
子模板中:
{% block content %}
这是子模板中 block中的代码
{% endblock %}
调用另一个 block 的代码
如果需要在模板中调用另外一个block中的代码,那么可以使用 {{ self.其他模版的名字() }}来调用
,示例代码如下:
{% block title %}
flask jinja2 模版继承
{% endblock %}
{% block content %}
{{ self.title() }}
这是子模板中 block中的代码
{% endblock %}
其他注意事项
子模板中的第一行代码,应该是继承的代码
子模板中放在了 block外的代码,不会被渲染