【Flask】02-模板

工欲善其事,必先利其器。

1. 模板使用

Flask的模板功能是基于Jinja2模板引擎实现的。接下来我们创建一个新的Flask运行文件,代码如下:

from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
    # return render_template('index.html', username="ydy", age=18)
    context = {
        "username": "ydongy",
        "age": 23,
        "gender": "male",
        "info": {
            "phone": "17xxxxxxxx",
            "email": "example@example.com"
        },
        "nums": [1, 2, 3, 4]
    }
    return render_template('index.html', **context)

代码中可以发现render_template是主要用来渲染模板,同时可以传入多个关键字参数,也可以对一个字典进行解包的形式传递参数。

2. 模板变量

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h1>index</h1>
{{ username }}
{{ age }}
{{ gender }}
{{ info.phone }}
{{ info["phone"] }}
{{ info.email }}
{{ info.aaa }}
<a href="{{ url_for('login',ref="/") }}">登陆</a>
</body>
</html>
  • {{变量名}}:获取模板传递过来的关键字参数,名称需要一致
  • {{变量名.键}}:接受一个字典参数,可以通过键获取值
  • {{变量名[键]}}:字典值的获取
  • {{url_for('视图名称',ref="当前url路径")}}:这里的url_for和视图中的用法一致,用于反转获取url地址,ref用于跳转之后指定是从那个页面跳转,如下的例子:
http://127.0.0.1:5000/login/?ref=%2F

3. 过滤器

有时候我们想要在模版中对一些变量进行处理,那么就必须需要类似于Python中的函数一样,可以将这个值传到函数中,然后做一些操作。在模版中,过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。

基本语法

{{ variable|过滤器名字 }},使用管道符号 | 进行组合。

3.1 default过滤器

1. {{ value|default('默认值') }}
2. {{ value|default('默认值',boolean=True) }}

示例:
{{ b | default('不存在',boolean=True) }}
{{ b or '不存在' }}
  1. 表示当value不存在的时候,那么就会使用default过滤器提供的默认值
  2. bollean=True:表示如果想要判断一个值是否为False(例如:None、空字符串、空列表、空字典等),也可以使用or来替代。

3.2 转义过滤器

@app.route("/filter/")
def my_filter():
    context = {
        "signature": '<script>alert("hello")</script>',
        "create_time": datetime.now()
    }
    return render_template('posts/filter.html', **context)

上面代码可以发现,传递的变量含有标准的html标签,如果想要获取这个字符串渲染成html标签的话就需要关闭自动转义,如以下的模板语法。

  1. safe过滤器:可以关闭一个字符串的自动转义。
  2. escape过滤器:对某一个字符串进行转义。
  3. autoescape标签,可以对他里面的代码块关闭或开启自动转义。
示例:
{#关闭自动转义渲染成html标签#}
<p>个性签名:{{ signature | safe }}</p>

{#开启转义阻止渲染成html标签#}
<p>个性签名:{{ signature | escape  }}</p>

{#关闭自动转义#}
{% autoescape off %}
  ......代码块
{% endautoescape %}

3.3 常用过滤器

  1. first(value):返回一个序列的第一个元素。names|first。
  2. format(value,*arags,**kwargs):格式化字符串。例如以下代码:
{{ "%s" - "%s"|format('Hello?',"Foo!") }}

>>>Helloo? - Foo!
  1. last(value):返回一个序列的最后一个元素。示例:names|last。
  2. length(value):返回一个序列或者字典的长度。示例:names|length
  3. join(value,d=u''):将一个序列用d这个参数的值拼接成字符串。
  4. safe(value):如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:content_html|safe
  5. int(value):将值转换为int类型。
  6. float(value):将值转换为float类型。
  7. lower(value):将字符串转换为小写。
  8. upper(value):将字符串转换为小写。
  9. replace(value,old,new): 替换将old替换为new的字符串。
  10. truncate(value,length=255,killwords=False):截取length长度的字符串。
  11. striptags(value):删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格。
  12. trim:截取字符串前面和后面的空白字符。
  13. string(value):将变量转换成字符串。
  14. wordcount(s):计算一个长字符串中单词的个数。

3.4 自定义模板过滤器

过滤器本质上就是一个函数。如果在模版中调用这个过滤器,那么就会将这个变量的值作为第一个参数传给过滤器这个函数,然后函数的返回值会作为这个过滤器的返回值。需要使用到一个装饰器:@app.template_filter('cut')

# 自定义过滤器,把hello替换为空字符串
@app.template_filter('cut')
def cut(value):
    value = value.replace("hello",'')
    return value
<p>{{ article|cut }}</p>

4. 判断语句

{% if statement %}
     ......代码块
{% endif %}

判断语句和python中的判断语句一致,也可以使用>,<,<=,>=,==,!=来进行判断,也可以通过and,or,not,()来进行逻辑合并操作。

5. for循环

{% for x in range(1,10) %}
     ......代码块
{% endfor %}

循环语句和python中同样类似,采用in来遍历所有的序列以及迭代器,但是注意jinja2中的循环没有breakcontinue如果你启用了jinja2.ext.loopcontrols扩展的话,你还可以在循环中使用{% break %}{% continue %}来控制循环执行。

Jinja2的循环内置变量主要有以下几个:

变量 内容
loop.index 循环迭代计数(从1开始)
loop.index0 循环迭代计数(从0开始)
loop.revindex 循环迭代倒序计数(从len开始,到1结束)
loop.revindex0 循环迭代倒序计数(从len-1开始,到0结束)
loop.first 是否为循环的第一个元素
loop.last 是否为循环的最后一个元素
loop.length 循环序列中元素的个数
loop.cycle 在给定的序列中轮循,如上例在”odd”和”even”两个值间轮循
loop.depth 当前循环在递归中的层级(从1开始)
loop.depth0 当前循环在递归中的层级(从0开始)

循环中使用if

{% for y in range(1,10) if y <= 5 %}
       ......代码块        
{% endfor %}

6. 宏

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

6.1 定义宏

{% macro input(name="",value="",type="text") %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}

6.2 使用宏

  • 直接导入宏内定义的函数
{% from "posts/macros.html" import input %}

{{ input(value="提交",type="submit") }}

上面代码定义宏就相当于创建一个input函数,参数包括:name,value,type,使用宏就相当于调用函数

  • 导入宏,通过宏调用
{{ macros.input(value="提交",type="submit") }}

6.3 导入宏

{#引入宏#}
{% from "posts/macros.html" import input %}
{% import"posts/macros.html" as macros %}

{#把当前变量传入到宏#}
{% import"posts/macros.html" as macros with context %}

如果想要在导入宏的时候,就把当前模版的一些参数传给宏所在的模版,那么就应该在导入的时候使用with context

6. include标签

这个标签相当于是直接将指定的模版中的代码复制粘贴到当前位置。

例如:下面这一部分代码是公共页脚代码templates/posts/footer.html

<footer>
    底部
</footer>

从当前页面引入页脚代码

{#使用公共模板#}
<ul>
    <div class="content">
        中间
    </div>
    {% include "posts/footer.html" %} {#相当于把代码复制在此处#}
</ul>

7. set和with语句

在模版中,可以使用set语句来定义变量。示例如下:

{% set username='zhangsan' %}
<p>用户名:{{ username }}</p>

一旦定义了这个变量,那么在后面的代码中,都可以使用这个变量,就类似于Python的变量定义是一样的。

with语句定义的变量,只能在with语句块中使用,超过了这个代码块,就不能再使用了。示例代码如下:

  • 方式一
{% with classroom = '一班' %}
<p>班级:{{ classroom }}</p>
{% endwith %}
  • 方式二
{% with %}
    {% set age=18 %}
    <p>age: {{ age }}</p>
{% endwith %}

8. 模板继承

模版继承可以把一些公用的代码单独抽取出来放到一个父模板中。以后子模板直接继承就可以使用了。提高代码的复用性

使用extends语句,来指明继承的父模板。父模板的路径,也是相对于templates文件夹下的绝对路径

{% extends "base.html" %}

如下定义一个父模板templates/posts/base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        {% block title %}

        {% endblock %}
    </title>
</head>
<body>
我是父模板里面的代码
{% block body_block %}
    我是父模板block中的代码
{% endblock %}
</body>
</html>

父模板代码中定义了两个block语句块,相当于预留块,只要在子模板中重写block语句块就可以实现不同的代码。

{# 导入父模板 #}
{% extends "posts/base.html" %}

{# 重写title #}
{% block title %}
    sub
{% endblock %}

{% block body_block %}
{# 调用父模板block中的代码,否则就被覆盖 #}
    {{ super() }}

{# 调用另一个block中的内容 #}
    {{ self.title() }}

    我是子模板block的代码
{% endblock %}

更多参考:
http://www.bjhee.com/flask-ad3.html
https://dormousehole.readthedocs.io/en/latest/quickstart.html#

原文地址:https://www.cnblogs.com/ydongy/p/13157574.html