Py进阶程序员

Flask框架之模板

2018-09-22  本文已影响311人  懵懂_傻孩纸

Jinja2模板引擎简介

模板

在前面的实例中,视图函数的主要作用是生成请求的响应,这是最简单请求.实际上,视图函数有两个作用:

在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本.

使用模板的好处

Jinja2

两个概念

渲染模板函数

使用

<h1>{{post.title}}</h1>

Jinja2模板中的变量代码块可以使任意Python类型或者对象,只要它能够被Python的str()方法转化为一个字符串就可以,比如,可以通过下面的方式显示一个字典或者列表中的某个元素

{{your_dict['key']}}
{{your_list[0]}}
{% if user %}
    {{ user }}
{% else %}
    hello!
<ul>
    {% for index in indexs %}
    <li> {{ index }} </li>
    {% endfor %}
</ul>

注释

{#{{ name }}#}

模板基本使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
我的模板html内容
</body>
</html>
image.png image.png
@app.route('/')
def index():
    return render_template('temp_demo1.html')

访问: htpp://127.0.0.1:5000/运行测试

模板变量

@app.route('/')
def index():
    # 往模板中传入的数据
    my_str = 'Hello Word'
    my_int = 10
    my_array = [3, 4, 2, 1, 7, 9]
    my_dict = {
        'name': 'xiaoming',
        'age': 18
    }
    return render_template('temp_demo1.html',
                           my_str=my_str,
                           my_int=my_int,
                           my_array=my_array,
                           my_dict=my_dict
                           )
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
我的模板html内容
<br/>{{ my_str }}
<br/>{{ my_int }}
<br/>{{ my_array }}
<br/>{{ my_dict }}

</body>
</html>
<br/> my_int + 10 的和为:{{ my_int + 10 }}
<br/> my_int + my_array第0个值的和为:{{ my_int + my_array[0] }}
<br/> my_array 第0个值为:{{ my_array[0] }}
<br/> my_array 第1个值为:{{ my_array.1 }}
<br/> my_dict 中 name 的值为:{{ my_dict['name'] }}
<br/> my_dict 中 age 的值为:{{ my_dict.age }}
my_int + 10 的和为:20 
my_int + my_array第0个值的和为:13 
my_array 第0个值为:3 
my_array 第1个值为:4 
my_dict 中 name 的值为:xiaoming 
my_dict 中 age 的值为:18

示例代码:

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def index():
    my_int = 18
    my_str = 'curry'
    my_list = [1, 5, 4, 3, 2]
    my_dict = {
        'name': 'durant',
        'age': 28
    }

    # render_template方法:渲染模板
    # 参数1: 模板名称  参数n: 传到模板里的数据
    return render_template('01_template.html',
                           my_int=my_int,
                           my_str=my_str,
                           my_list=my_list,
                           my_dict=my_dict)


if __name__ == '__main__':
    app.run(debug=True)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>我是模板</h2>
{{ my_int }}
<br>
{{ my_str }}
<br>
{{ my_list }}
<br>
{{ my_dict }}
<hr>
<h2>模板的list数据获取</h2>
<hr>
{{ my_list[0] }}
<br>
{{ my_list.1 }}
<hr>
<h2>字典数据获取</h2>
<hr>
{{ my_dict['name'] }}
<br>
{{ my_dict.age }}
<hr>
<h2>算术运算</h2>
<br>
{{ my_list.0 + 10 }}
<br>
{{ my_list[0] + my_list.1 }}
</body>
</html>

过滤器

过滤器本质就是函数。

有时候我们不仅仅只是需要输出变量的值,我们还需要修改变量的显示,甚至格式化、运算等等,而在模板中是不能直接调用Python中的某些方法,那么这就用到了过滤器

使用方法:

链式调用

在Jinja2中,过滤器支持链式调用,示例如下:

{{'hello word' | reverse | upper}}

输出结果为:

DROW OLLEH

常见内建过滤器

<p>{{ '<em>hello</em>' | safe }}</p>
<p>{{ 'hello' | capitalize }}</p>
<p>{{ 'HELLO' | lower }}</p>
<p>{{ 'hello' | upper }}</p>
<p>{{ 'hello' | title }}</p>
<p>{{ 'olleh' | reverse }}</p>
<p>{{ '%s is %d' | format('name',17) }}</p>
<p>{{ '<em>hello</em>' | striptags }}</p>
<p>{{ 'hello every one' | truncate(9)}}</p>

列表操作

<p>{{ [1,2,3,4,5,6] | first }}</p>
<p>{{ [1,2,3,4,5,6] | last }}</p>
<p>{{ [1,2,3,4,5,6] | length }}</p>
<p>{{ [1,2,3,4,5,6] | sum }}</p>
<p>{{ [6,2,3,1,5,4] | sort }}</p>

语句块过滤

{% filter upper %}
    #一大堆文字#
{% endfilter %}

自定义过滤器

过滤器本质是函数,当模板内置的过滤器不能满足需求,可以自定义过滤器。自定义过滤器有两种方式实现。

重要:自定义过滤器名称如果和内置过滤器重名,会覆盖内置的过滤器

需求:添加列表反转的过滤器

方式一

通过调用应用程序实例的 add_template_filter 方法实现自定义过滤器。该方法第一个参数是函数名,第二个参数是自定义的过滤器名称:

def do_listreverse(li):
    # 通过原列表创建一个新列表
    temp_li = list(li)
    # 将新列表进行返转
    temp_li.reverse()
    return temp_li

app.add_template_filter(do_listreverse,'lireverse')

方式二

用装饰器来实现自定义过滤器。装饰器传入的参数是自定义的过滤器名称。

@app.template_filter('lireverse')
def do_listreverse(li):
    # 通过原列表创建一个新列表
    temp_li = list(li)
    # 将新列表进行返转
    temp_li.reverse()
    return temp_li
<br/> my_array 原内容:{{ my_array }}
<br/> my_array 反转:{{ my_array | lireverse }}
my_array 原内容:[3, 4, 2, 1, 7, 9] 
my_array 反转:[9, 7, 1, 2, 4, 3]

完整代码:

from flask import Flask, render_template

app = Flask(__name__)

# 1.自定义列表反转函数
@app.template_filter('list_reverse')
# 方法二:使用装饰器
def list_reverse(list):
    # list = []
    list.reverse()
    return list

# 2.将自定义的函数添加到flask过滤器中
app.add_template_filter(list_reverse, 'list_reverse')


@app.route('/')
def index():
    list = [1, 3, 4, 5, 2]  # 2,5,4,3,1
    return render_template('03_diy.html', list=list)


if __name__ == '__main__':
    app.run(debug=True)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>自定义过滤器</h2>
<br>
{{ list }}
<br>
{{ list | list_reverse }}
</body>
</html>

控制代码块

控制代码块主要包含两个:

if/else  if/else  / endif
for  /  endfor

if语句

Jinja2语法中的if语句跟Python中的if语句相似,后面的布尔值或者返回布尔值的表达式将决定代码中那个流程会被执行:

 {% if item.id != 5  %}

        {% if loop.index == 1 %}

            <li style="background-color: deeppink">{{ item.value }}</li>
            
        {% endif %}

  {% endif %}

循环

{% for post in posts %}
    <div>
        <h1>{{ post.title }}</h1>
        <p>{{ post.text | safe }}</p>
    </div>
{% endfor %}
{% for post in posts if post.text %}
    <div>
        <h1>{{ post.title }}</h1>
        <p>{{ post.text | safe }}</p>
    </div>
{% endfor %}
变量 描述
loop.inde 当前循环迭代的次数(从1开始)
loop.index0 当前循环迭代的次数(从0开始)
loop.revindex 到循环结束需要迭代的次数(从1开始)
loop.revindex0 到循环结束需要迭代的次数(从0开始)
loop.frist 如果是第一次迭代,为True
loop.last 如果是最后一次迭代,为True
loop.length 序列中的项目数
loop.cycle 在一串序列间期取值的辅助函数

实例程序

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def index():
    # 只显示4行代码,颜色为黄绿红紫
    my_list = [
        {
            "id": 1,
            "value": "我爱工作"
        },
        {
            "id": 2,
            "value": "工作使人快乐"
        },
        {
            "id": 3,
            "value": "沉迷于工作无法自拔"
        },
        {
            "id": 4,
            "value": "日渐消瘦"
        },
        {
            "id": 5,
            "value": "以梦为马,越骑越傻"
        }
    ]
    return render_template('04_hold.html', my_list=my_list)


if __name__ == '__main__':
    app.run(debug=True)

html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
控制代码块使用
<br>
<hr>

{% for item in my_list %}

    {% if item.id != 5  %}

        {% if loop.index == 1 %}

            <li style="background-color: deeppink">{{ item.value }}</li>

        {% elif loop.index == 2 %}

            <li style="background-color: cyan">{{ item.value }}</li>

        {% elif loop.index == 3 %}

            <li style="background-color: darkorchid">{{ item.value }}</li>

        {% elif loop.index == 4 %}

            <li style="background-color: yellow">{{ item.value }}</li>


        {% endif %}



    {% endif %}


{% endfor %}



</body>
</html>

模板继承

在模板中,可能会遇到以下情况:

像遇到这种情况,可以使用Jinja2模板中的继承来进行实现

模板继承是为了重用模板中的公共内容.一般Web开发中,继承主要使用在网站的顶部菜单,底部.这些内容可以定义在父模板中,子模板直接继承,不需要重写

{% block top %}  {% endblock%}

示例代码:

from flask import Flask,render_template

app = Flask(__name__)


@app.route('/parent')
def parent():
    return render_template('06_one.html')

@app.route('/child')
def child():
    return render_template('07_tow.html')


if __name__ == '__main__':
    app.run(debug=True)
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<body>


<h2>我是头部</h2>
<hr>


{# 将父模板中需要重写的内容使用block包含起来 #}
{% block content %}
<h2>我是父模板内容</h2>
{% endblock %}
<hr>


<h2>我是底部</h2>
</body>
</html>
{# 1 使用extends关键字集成模板 #}
{% extends '06_one.html' %}


{#  重写block #}
{% block content %}

    <h2>我是子模板内容</h2>

{% endblock %}

特有变量和函数

你可以在自己的模板中访问一些 Flask 默认内置的函数和对象

config

你可以从模板中直接访问Flask当前的config对象

{{config.SQLALCHEMY_DATABASE_URI}}
sqlite:///database.db

request

就是Flask中代表当前请求的request对象

{{request.url}}
http://127.0.0.1

session

为Flask的session对象

{{session.new}}
True

g变量

在视图函数中设置g变量的name属性的值,然后在模板中直接可以取出

{{ g.name }}

url_for()

url_for会根据传入的路由器函数名,返回该路由对应的URL,在模板中始终使用url_for()就可以安全的修改路由绑定的URL,则不比担心模板中渲染出错的链接:

{{url_for('home')}}
/

如果我们定义的路由URL是带有参数的,则可以把它们作为关键字参数传入url_for(),Flask会把他们填充进最终生成的URL中:

{{ url_for('post', post_id=1)}}
/post/1
上一篇下一篇

猜你喜欢

热点阅读