Day 6 jinja (1)

前言

今天要来看 jinja 这个模板引擎。简单来说,它的功能就是在 HTML 里面执行一般程序,等等看过范例之後应该可以更清楚它的作用。

虽然说是在执行一般程序,但是其语法和一般程序也有一些些差别,我自己的习惯是照着一般程序的语法,如果错了的话再去搜寻正确的用法。

前置作业

这次并非只需要简单地把程序码复制到 app.py 而已,我们需要先建立一个名为 templates 的资料夹,名字必须完全符合,等等会需要把 HTML 及以後会用到的 jinja 模板放在里面。

范例一

建立完资料夹後,我们来看看以下这份程序码,请注意 index.html 需要放在 templates 目录内。

app.py


from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def index_page():
    name = "cat"
    return render_template("index.html", username=name)


app.run(host="127.0.0.1", port=8080, debug=True)

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Index</title>
</head>
<body>
    {{ username }}
</body>
</html>

app.py 中,我们看到了一个新的函式:render_template,不例外地,他也需要 import。它的功用是把一个 template 送入 jinja 跑,然後就可以得到一个字串,内容就是跑出来的 HTML,最後会把他 return 回去,这样一来,使用者就可以收到一个漂亮的 HTML,而非之前连 head 都没有的单纯内容。有了它的好处是,我们不需要把超长的 HTML 放在 python 档案里面,而且可以用比较漂亮的方式生出 HTML,等等在看 for 回圈的时候会更有感觉。

它需要一个 template name,以此处为例就是 index.html。接下来会看到他後面的 username=name,他会把刚刚定义的 name 传入 template 给 jinja 处理,而在 jinja 里面,他的名字叫做 username。接着我们看到 index.html,它里面有一行 {{ username }},在 jinja 里面,我们使用大括号来表示我们存取的变数,此处就是刚刚在 redner_template 传入的 name

这边值得注意的是,jinja 只会去处理大括号的部分,其他 HTML 的元素他秋毫无犯,会原汁原味秀出来。

范例二

刚刚看了基本的使用方法,现在来看看 if 要怎麽处理。

app.py

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def index_page():
    state = "running"
    return render_template("index.html", state=state)


app.run(host="127.0.0.1", port=8080, debug=True)

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Index</title>
</head>
<body>
    {% if state == "running" %}
    <p>running</p>
    {% else %}
    <p>terminated</p>
    {% endif %}
</body>
</html>

我们这次传入了 state 这个变数,然後在 jinja 里面判断他是否等於 running。这里要注意的是他 if 并不是跟刚刚一样用两个大括号,而是一个大括号和一个百分符号。这两种的差别在於他是不是一个 statement,{% %} 是给 statement 用的,而 {{ }} 则是用来存取内容用的。还有跟 python 不太一样的是他有 endif,要记得加。也因为他已经有了 endif,所以他不会管你的缩排。

还有一个要注意的是,我们的 <p>running</p><p>terminated</p> 并没有加上大括号,因为他就是一般的 HTML element。如果要把 running 换成 state,那就要改成 <p>{{ state }}</p>

范例三

接下来就要讲回圈,比较特别的是 jinja 只有 for 没有 while,以下是一个范例。

app.py

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def index_page():
    users = ["Mary", "Cat", "Meow", "Harry"]
    return render_template("index.html", users=users)


app.run(host="127.0.0.1", port=8080, debug=True)

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Index</title>
</head>
<body>
    <h1>User list</h1>
    <ul>
        {% for user in users %}
        <li>{{ user | upper }} ({{ loop.index }})</li>
        {% endfor %}
    </ul>
</body>
</html>

在这个范例中我们传入了一个叫做 users 的 list,接下来我们交给 jinja 处理,他帮我们跑一个 for 回圈 (注意他也是 statement,所以要用 {% %}),依序把 users 里的 user 取出来,然後放在 li 里面。接下来看到後面的 loop.index,他是一个预设就存在的变数,他表示了平常在 list 看到的 index,但他是从 1 开始数,如果要从零开始数需要用 loop.index0

最後看到在 user 後面的 | upper,他是一个 filter,就是等同於平常用到的 str.upper(),只是在此处我们习惯使用 filter。在此处当然可以直接 {{ user.upper() }} 就好,但是有些时候没有办法用 python 的语法来处理,像是如果我们直接使用 int(),他会告诉我们 undefined,这时候就需要用 | int 来达成需求。

如果想要加入自定义的 filter 的话,flask 已经有一个包装好的方法可以处理,以下是范例。

app.py

from flask import Flask, render_template
app = Flask(__name__)

@app.template_filter()
def get_initial(s):
    return s[0]

@app.route("/")
def index_page():
    user = "Cat"
    return render_template("index.html", user=user)


app.run(host="127.0.0.1", port=8080, debug=True)

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Index</title>
</head>
<body>
    {{ user | get_initial }}
</body>
</html>

可以看到在 app.py 的最前面我们使用了 app.template_filter,让他装饰了一个会丢出第一个字母的函式,接下来在 index.html 我们就直接使用了这个 filter,不需要把它当成参数放在 render_template,也不需要特别 import,他就直接变成了预设就存在的 filter。

References

Basic Syntax of Jinja
Python jinja2 + flask
Custom Jinja template filters in Flask


<<:  Day6 javascript 函数

>>:  AE卷轴制作4-Day5

纠正不合规问题并减轻风险, 您最关心的项目为何?

基於风险的方法已广泛用於各个领域,例如决策,审计,网络安全,银行等。“风险是不确定性对目标的影响。”...

【Day27】为爬虫加上通知 - 透过 POSTMAN 了解 LINE Notify 如何使用

爬虫完成後没发出通知,就像是黯然销魂饭少了洋葱 为什麽通知很重要? 在爬虫的运作完全自动化的状态下...

Chapter2 - Canvas动画(II)用国中数学拆解Ease-out和Ease-in

如何计算每一侦的位移 首先我们改写一下昨天的格式,还记得昨天我们用到的是这样的写法: cursorX...

Python 练习

今天也是跟昨天一样,要来练习比较难的题目,就是APCS啦,今天要来练习的题目是APCS 106年3月...

17.移转 Aras PLM大小事-用Excel复制料号去查询

我想看标题一定会困惑这是什麽 先解释一下使用者最常用Excel作报表 然後想复制之後快速查询特定料号...