Flask模板jinja2
模板预热
在渲染模板的时候,默认会从项目根目录下的‘templates‘目录下查找模板。
如果不想把模板文件放在‘templates‘目录下,那么可以在‘Flask‘初始化的时候指定‘template_folder‘来指定模板的路径
模块传参数
1.在使用‘render_template‘渲染模板的时候,可以传递关键字参数。以后直接在模板中使用就可以了
2.如果你的参数过多,那么可以将所有的参数放到一个字典中,然后再传这个字典参数的时候,使用两个星号,将字典打散成关键字参数
3.如果想要再HTML中访问我们传递的参数 比如传递的是 username=‘xiaoxin‘
如果是关键字参数 直接{{username}},就可以将我们的参数对应的内容映射到前端页面上
如果传递的是字典 比如
content = {‘name‘:‘age‘} 那么就可以{{content.name}} 就能将里面的age映射到前端上
使用**content 相当于将字典里面的参数,变成关键字传参,然后就可以直接{{username}},将我们参数的内容映射到前端网页上
模板中使用url_for
模板中的url_for跟我们后台视图函数中的url_for使用起来基本是一模一样的,也是传递视图函数的名字,也可以传递参数
再html里面使用的时候,需要再urlfor 左右两边加上 {{url_for(‘func‘)}}
过滤器的基本使用
有时候我们想要再模板中对一些变量进行处理,那么就必须需要类似于Python中的函数一样,可以将这个值传到函数中,然后做一些操作
基本语法:
{{variable|过滤器名字}}。使用管道符号‘|‘进行组合
过滤器是通过管道符号(|)进行使用的,列如{{name|length}},将返回name的长度。过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。Jinja2中内置了许多过滤器,再这里可以看到所有的过滤器,现在对一些常用的过滤器进行详解:
abs(value):返回一个数的绝对值 列如-1|abs
default(value,default_value,boolean=false):如果当前变量没有值e,则会使用参数中的值来代替。{{name|defaule(‘xiaotuo‘)}} --如果name不存在,则会使用xiaotuo来替代.boolean=False默认是再只有这个变量为undefined的时候才会使用default中的值,如果想使用python的形式判断是否为false(列如:None,空字符串,空列表,空字典等),则可以传递boolean=true
也可以使用or来替代default(‘默认值‘,boolean=True).例如
{{singature or ‘此人很懒,没人留下说明‘}}
自动转义过滤器:
escape(value)或e:转义字符. 会将< 、>等符号转义成HTML中的符号。列如:content|escape 或content|e
safe(value):如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:content_html|safe
autoescape标签,可以对他里面的代码块关闭或开启自动转义
{%autoescape off/on%} off是关闭自动转义 on是开启自动转义
.....代码块
{%endautoescape%}
first(value):返回一个序列的第一个元素。names|first
format(value,*args,**kwargs):格式化字符串。例如
{{"%s-%s"|format(‘hello?‘,"Foo!”)}} 将输出: hello?-Foo!
last(value):返回一个序列的最后一个元素。示例names|last
length(value):返回一个序列或者字典的长度。示例names|length
join(value,d=u"):将一个序列用d这个参数的值拼接成字符串
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): 计算一个长字符串中单词的个数
自定义模板过滤器
过滤器本质上就是一个函数,如果在模板中调用这个过滤器,那么就会将这个变量的值作为第一个参数传给过滤器这个函数,然后函数的返回值会作为这个过滤器的返回值。需要使用到一个装饰器 @app.template_filter(‘cut‘)
1.在python文件中,写好自己的过滤器。
@app.template_filter(‘cut‘) #装饰器里面传的我们自定义过滤器的名字,方便再HTML中使用
def cut(value): value是当再html中调用这个自定义过滤器的时候,会将调用这个自定义过滤器的变量传给value
value = value.replace(‘hello‘,‘‘)
return value
2.在HTML中
< p>{{story|cut}} < /p>
控制语句详解
所有的控制语句都是放在{%....%}中,并且有一个语句{%endxxx%}来进行结束.Jinja2中 常用的控制语句有if/for....in...,现对他们进行详解
1.‘if‘: if语句和python中的类似,可以使用>,<,<=,>=,==,!=来进行判断,也可以通过‘and or not,()‘来进行逻辑合并操作,以下看列子
+ {% if kenny.sick %} + kenny is sick. + {% elif kenny.dead %} + You killed Kenny! You bastard!!! + {%else%} + Kenny looks okay---so far + {%endif%}
2.‘for....in...‘:‘for‘循环可以遍历任何一个序列包括数组、字典、元组。并且可以进行反向遍历。以下将用几个列子进行解释:
普通的遍历
+ < ul> + {%for user in usres%} + < li>{{user.username|e}} < /li> + {%endfor%} + < /ul>
遍历字典:
+ < dl> + {%for key,value in my_dice.iteritems() %} + < dt> {{key|e}}</ dt> + < dd> {{value|e}}< /dd> + {{%endfor%}} + < /dl>
如果序列中没有值的时候,进入‘else‘
+ < ul> + {%for user in usres%} + < li>{{user.username|e}} < /li> + {%else%} + < li>< em>no users found< /em>< /li> + {%endfor%} + < /ul>
并且Jinja中的for循环还包含以下变量,可以用来获取当前的遍历状态:
变量 描述
loop.index 当前迭代的索引(从1开始)
loop.index0 当前迭代的索引(从0开始)
loop.first 是否是第一次迭代,返回Ture或False
loop.last 是否是最后一次迭代,返回True或False
loop.length 序列的长度
另外,不可以使用continue和break表达式来控制循环的执行
宏的使用
宏的概念和基本使用
模板中的宏跟python中的函数类似,可以传递函数,但是不能有返回值,可以将一些经常用到的代码片段放到宏中,然后把一些不固定的值抽取出,来当成一个变量,使用宏的时候,参数可以为默认值。以下将用一个列子来进行解释:
定义宏
+ {%macro input(name,value="",type=‘text‘)%} + < input type="{{type}}",name="{{name}}",value="{{value|e}}"> + {%endmacro%}
以上列子可以抽出了一个input标签,指定了一些默认参数。那么我们以后创建‘input‘标签的时候,可以通过她快速的创建
使用宏
+ < p>{{input(‘usename‘) }}< /p> + < p>{{input(‘password‘,type=‘password‘) }} < /p>
import语句
在真实的开发中,会将一些常用的宏单独放在一个文件中,在需要使用的时候,再从这个文件中进行导入。‘import‘语句的用法跟‘python‘中的‘import‘类似,可以直接‘import....as....‘,也可以 from....import.... 或者 from....import....as...,假设现在有一个文件,叫做forms.html,里面有两个宏分别为 input和textarea 如下
+ {%macro input(name,value="",type=‘text‘)%} - < input type="{{type}}",name="{{name}}",value="{{value|e}}"> + {%endmacro%} + {%macro textarea(name,value="",rows=10,cols=40)%} - < textarea name="{{name}}" rows="{{rows}}" cols="{{cols}}">{{value|e}} < /textarea> + {%endmacro%}
导入宏的列子
宏文件路径,不要以相对路径去寻找,都要以‘templates‘作为绝对路径去找
如果想要在导入宏的时候,就把当前模板的一些参数传给宏所在的模板,那么就应该在导入的时候使用with context 示例
from ‘xxx.html‘ import input with context
+ 1.import....as....形式: + {%import ‘forms.html‘ as forms%} + < dl> + < dt>Username< /dt> + < dd>{{forms.input(‘username‘) }} < /dd> + < dt>Password< /dt> + < dd>{{forms.input(‘password‘,type=‘password‘) }} < /dd> + < /dl> + < p> {{forms.textarea(‘comment‘) }} < /p> + 2.from...import....as..../from....import...形式 + {%from ‘forms.html‘ import input as input_field,textarea %}
include标签
这个标签相当于是直接将指定的模板代码复制粘贴到当前位置
‘include‘标签,如果想要使用父模板中的变量,直接用就可以了,不需要使用with context
include的路径,也是跟import 一样,直接从‘templates‘根目录下去找,不要以相对路径去找
{%include ‘路径名.html‘%}
set和with语句以及模板中定义变量
set语句:
在模板中,可以使用‘set‘语句来定义变量,示例如下
{%set username=‘小鑫‘%}
一旦定义了这个变量,那么在后面的代码中,都可以使用这个变量,就类似于python的变量定义是一样的
with语句:
with语句定义的变量,只能在‘with‘语句块中使用,超过了这个代码块,就不能在再使用了。示例代码块如下
+ {%with classroom=‘xiaoxin1‘%} + < p> 班级: {{classroom}} < /p> + {%endwith%}
with语句也不一定要跟一个变量,可以定义一个空的‘with‘语句,以后再‘with’块中通过‘set‘定义的变量,就只能再这个‘with‘块中使用了
+ {%with %} + {%set classroom=‘xiaoxin1‘%} + < p> 班级: {{classroom}} < /p> + {%endwith%}
加载静态文件(图片、CSS、JS)
1.加载静态文件使用的是url_for函数,然后第一个参数需要为‘static‘,第二个参数需要为一个关键字参数 ‘filename="路径" ‘ 示例:
{{url_for("static",filename="xxx") }}
路径查找,要以当前项目的‘static’目录作为根目录
模板继承详解
为什么需要模板继承
模板继承可以把一些公用的代码单独抽取出去放到一个父模板中,以后子模版直接继承就可以使用了,这样可以减少重复性的代码,并且以后修改起来也比较方便
模板继承语法:
使用‘extends关键语句‘,来指明继承的父模板。父模板的路径,也是相对于templates文件夹下的绝对路径。示例代码如下
{%extends ‘base.html‘%}
block语法:
一般在父模板中,只能定义一些公用的代码。子模版可能要根据具体的需求实现不同的代码。这时候父模板就应该有能力提供一个接口,让子模板来实现,从而实现具体业务需求的功能。
在父模板中
{%block block的名字%} {%endblock%}
在子模版中 也叫方法重写(重写父模板里面的block)
+ {%block block的名字%} + 子模版中的代码 + {%endblock%}
调用父模板代码blcok中的代码
默认情况下,子模版如果实现了父模板定义的block,那么子模版block中的代码就会覆盖掉父模板中的代码。如果想要在子模版中仍然保持父模板中的代码,那么可以使用{{super()}}来实现。 示例如下
父模板
+ {%block block的名字%} + 这是父模板里面的代码 + {%endblock%}
子模版
+ {%block block的名字%} + {{super()}} + 这是子模版中的代码 + {%endblock%}
调用另外一个block中的代码
如果想要在另外一个模板中使用其他模板中的代码,那么可以通过{{self.其他block名字()}} 就可以了 示例代码如下
+ {%block title%} + 这是首页 + {%endblock%} + + {%block body_block%} + {{self.title()}} + 我是子模版中的代码 + {%endblock%}
其他注意事项
1.子模版中的代码,第一行,应该是‘extends‘
2.子模版中,如果想要实现自己的代码,应该放到block中,如果放到其他地方,那么就不会被渲染