模板渲染

先创建一个目录,templates,将模板文件放到目录中,默认查找templates目录
return render_template("模板文件名字")

指定模板目录

template_folder="模板目录"

  1. app = Flask(__name__, template_folder=r"./demo")

模板传参

  1. return render_template("index.html", username="xxxx")
  2. {{ username }}
  3. context = {
  4. xxx: "xxx"
  5. }
  6. return render_template("index.html", context=context)
  7. {{ context.xxx }}
  8. context = {
  9. xxx: "xxx"
  10. }
  11. return render_template("index.html", **context)
  12. {{ xxx }}

模板过滤器

过滤器是通过管道符号(|)进⾏使⽤的,例如:{{ name|length }},将返回
name的⻓度。过滤器相当于是⼀个函数,把当前的变量传⼊到过滤器中,然后
过滤器根据⾃⼰的功能,再返回相应的值,之后再将结果渲染到⻚⾯中。Jinja2
中内置了许多过滤器,在这⾥可以看到所有的过滤器

  • abs(value):返回⼀个数值的绝对值。


  • default(value,default_value,boolean=false):如果当前变量没有值,则会

使⽤参数中的值来代替。name|default(‘juran’)——如果name不存在,则会
使⽤juran来替代。boolean=False默认是在只有这个变量为undefined的时
候才会使⽤default中的值,如果想使⽤python的形式判断是否为false,则
可以传递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=u’’):将⼀个序列⽤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):计算⼀个⻓字符串中单词的个数。

    控制语句

所有的控制语句都是放在{% … %}中,并且有⼀个语句{% endxxx %}来进行结束,Jinja中常用的控制语句有if/for..in..
if:if语句和python中的类似,可以使用>,<,<=,>=,==,!=来进⾏判断,也可以通过and,or,not,()来进行逻辑合并操作

  1. {% if kenny.sick %}
  2. Kenny is sick.
  3. {% elif kenny.dead %}
  4. You killed Kenny! You bastard!!!
  5. {% else %}
  6. Kenny looks okay --- so far
  7. {% endif %}

for…in…:for循环可以遍历任何⼀个序列包括列表、字典、元组。并且可以进
⾏反向遍历
普通的遍历

  1. <ul>
  2. {% for user in users %}
  3. <li>{{ user.username|e }}</li>
  4. {% endfor %}
  5. </ul>

遍历字典

  1. <dl>
  2. {% for key, value in my_dict.iteritems() %}
  3. <dt>{{ key|e }}</dt>
  4. <dd>{{ value|e }}</dd>
  5. {% endfor %}
  6. </dl>

如果序列中没有值的时候,进入else

  1. <ul>
  2. {% for user in users %}
  3. <li>{{ user.username|e }}</li>
  4. {% else %}
  5. <li><em>no users found</em></li>
  6. {% endfor %}
  7. </ul>

并且Jinja中的for循环还包含以下变量,可以⽤来获取当前的遍历状态
image.png
另外,不可以使⽤continue和break表达式来控制循环的执行。

宏和import

模板中的宏跟python中的函数类似,可以传递参数,但是不能有返回值,可以
将⼀些经常用到的代码片段放到宏中,然后把⼀些不固定的值抽取出来当成⼀
个变量

  1. {% macro input(name, value='', type='text') %}
  2. <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
  3. {% endmacro %}

以上例⼦可以抽取出了⼀个input标签,指定了⼀些默认参数。那么我们以后创建input标签的时候,可以
通过他快速的创建:

  1. 1 <p>{{ input('username') }}</p>
  2. <p>{{ input('password', type='password') }}</p>

import语句

在真实的开发中,会将⼀些常⽤的宏单独放在⼀个⽂件中,在需要使⽤的时
候,再从这个⽂件中进⾏导⼊。import语句的⽤法跟python中的import类似,
可以直接import…as…,也可以from…import…或者from…import…as…,假
设现在有⼀个⽂件,叫做macro.html,⾥⾯有两个宏分别为input和textarea
macro.html:

  1. {% macro input(name, value='', type='text') %}
  2. <input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
  3. {% endmacro %}
  4. {% macro textarea(name, value='', rows=10, cols=40) %}
  5. <textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols }}">{{ value|e }}</textarea>
  6. {% endmacro %}

导⼊宏的例⼦
1.import…as…形式

  1. {% import 'macro.html' as macro %}
  2. <tr>
  3. <td>⽤户名:</td>
  4. <td>{{ macro.input('username') }}</td>
  5. </tr>

2.from…import…as…/from…import…形式

  1. {% from "macro.html" import input %}
  2. <tr>
  3. <td>密码:</td>
  4. <td>{{ input("password",type="password") }}</td>
  5. </tr>

另外需要注意的是,导⼊模板并不会把当前上下⽂中的变量添加到被导⼊的模
板中,如果你想要导⼊⼀个需要访问当前上下⽂变量的宏,有两种可能的⽅法

  • 显式地传⼊请求或请求对象的属性作为宏的参数
  • 与上下⽂⼀起(with context)导⼊宏

与上下⽂中⼀起(with context)导⼊的⽅式

  1. {% import 'macro.html' as macro with context %}

include和set

include语句

include 语句可以把⼀个模板引⼊到另外⼀个模板中,类似于把⼀个模板的代
码copy到另外⼀个模板的指定位置

  1. {% include 'header.html' %}
  2. 主体内容
  3. {% include 'footer.html' %}

赋值(set)语句

  1. {% set name='xxx' %} #全局
  2. {% with %}
  3. {% set name='xxx' %} # 局部
  4. {% endwith %}
  5. {% with xxx='' %} # 局部
  6. {% endwith %}

有时候我们想在在模板中添加变量,这时候赋值语句(set)就派上⽤场了

  1. {% set name='ecithy' %}

那么以后就可以使⽤ name 来代替 juran 这个值了,同时,也可以给他赋值为
列表和元组:

  1. {% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}

赋值语句创建的变量在其之后都是有效的,如果不想让⼀个变量污染全局环
境,可以使⽤ with语句来创建⼀个内部的作用域,将 set 语句放在其中,这样
创建的变量只在 with代码块中才有效

  1. {% with %}
  2. {% set foo = 42 %}
  3. {{ foo }} foo is 42 here 4
  4. {% endwith %}

也可以在 with 的后面直接添加变量,比如以上的写法可以修改成这样:

  1. {% with foo = 42 %}
  2. {{ foo }}
  3. {% endwith %}

这两种方式都是等价的,⼀旦超出 with代码块,就不能再使⽤ foo 这个变量
了。

模版继承

作用:代码的复用,和类的思想类似(可继承、重写)
{% extends '父模板.html' %}
继承的注意点

  1. 1. {% extends 'base.html' %} 放到block模块上面
  2. 2. 子模板不可以多继承
  3. 3. 子模板只能重写父模板中的block,自己定义的block不显示,没有在block模块中的标签也不会显示
  4. 4. 调用父模板中的block {{ super() }}
  5. 5. 父模板中block,是可以嵌套的

Flask中的模板可以继承,通过继承可以把模板中许多重复出现的元素抽取出
来,放在父模板中,并且父模板通过定义 block 给⼦模板开⼀个口,子模板根
据需要,再实现这个 block ,假设现在有⼀个 base.html 这个⽗模板

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <link rel="stylesheet" href="base.css" />
  5. <title>{% block title %}{% endblock %}</title>
  6. {% block head %}{% endblock %}
  7. </head>
  8. <body>
  9. <div id="body">{% block body %}{% endblock %}</div>
  10. <div id="footer">
  11. {% block footer %}
  12. &copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>
  13. {% endblock %}
  14. </div>
  15. </body>
  16. </html>

以上⽗模板中,抽取了所有模板都需要⽤到的元素 html 、 body 等,并且对于
⼀些所有模板都要用到的样式⽂件 style.css 也进行了抽取,同时对于⼀些子
模板需要重写的地方,比如 title 、 head 、 body 都定义成了 block ,然后
子模板可以根据自己的需要,再具体的实现。

  1. {% extends "base.html" %}
  2. {% block title %}⾸⻚{% endblock %}
  3. {% block head %}
  4. {{ super() }}
  5. <style type="text/css">
  6. .detail{
  7. color: red;
  8. }
  9. </style>
  10. {% endblock %}
  11. {% block content %}
  12. <h1>这⾥是⾸⻚</h1>
  13. <p class="detail">
  14. ⾸⻚的内容
  15. </p>
  16. {% endblock %}

首先第⼀行就定义了子模板继承的父模板,并且可以看到⼦模板实现了 title
这个 block ,并填充了自己的内容,再看 head 这个 block ,里面调用了
super() 这个函数,这个函数的⽬的是执行父模板中的代码,把父模板中的内
容添加到子模板中,如果没有这⼀句,则父模板中处在 head 这个 block 中的
代码将会被子模板中的代码给覆盖掉。

另外,模板中不能出现重名的 block,如果⼀个地方需要用到另外⼀个 block
中的内容,可以使用 self.blockname 的方式进行引用

  1. <title>
  2. {% block title %}
  3. 这是标题
  4. {% endblock %}
  5. </title>
  6. <h1>{{ self.title() }}</h1>

以上示例中 h1 标签重⽤了 title这个 block中的内容,子模板实现了 title这个 block,h1 标签也能拥有这个值。另外,在子模板中,所有的文本标签和代码都要添加到从父模板中继承的 block中。否则,这些文本和标签将不会被渲染

加载静态资源文件

创建static目录,静态资源文件放到这个目录下面

  1. <link rel="stylesheet" href="{{ url_for('static', filename='css/index.css') }}">
  2. <script src="{{ url_for('static', filename='js/index.js') }}"></script>
  3. <img src="{{ url_for('static', filename='images/demo.jpg') }}" alt="">

还可以自定义资源文件的目录

  1. app = Flask(__name__,static_folder='./static')