今天要继续看 jinja 的使用,昨天的内容比较接近一般的变数存取、if、for 的使用,而今天的内容则是类似自定义函数。
先来看个范例。请注意 index.html
和 msg.jinja
都要放在昨天提到的 templates/
里面。
app.py
from flask import Flask, render_template, flash
app = Flask(__name__)
@app.route("/")
def index_page():
users = ["Mary", "Cat", "Meow", "Harry"]
flash("meow", category="cat")
return render_template("index.html", users=users)
app.config["SECRET_KEY"] = "rc498mt6848"
app.run(host="127.0.0.1", port=8080, debug=True)
index.html
{% from 'msg.jinja' import display_msg %}
<!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>
{{ display_msg(get_flashed_messages(with_categories=True)) }}
<h1>User list</h1>
<ul>
{% for user in users %}
<li>{{ user }} ({{ loop.index }})</li>
{% endfor %}
</ul>
</body>
</html>
msg.jinja
{% macro display_msg(messages) %}
<div id="messages">
{% if messages %}
{% for category, message in messages %}
<div class="{{ category }}">
<span>{{ message }}</span>
</div>
{% endfor %}
{% endif %}
</div>
{% endmacro %}
这次的档案比较多,也比较繁杂,我们一个一个慢慢看。
app.py
基本上就是昨天用来解释 for 的范例,但是新加入了一个叫做 flash
的函式 ,它的用途是把後端的资料送到前端显示。比如说可能使用者在注册帐号的时候,使用者名称已经被用过了,那後端就可以发一条警告讯息到前端通知使用者这个名称被使用了。虽然这里说是前端,但基本上它也是由 jinja 去跑的,所以需要用 render_template
。在他的後面我们加了一个 category
的参数,这是选用,它的功能就是放一个标签给这条讯息,让前端可以因应,例如说上面的名称已被使用可能就是 warning
,而注册成功可能就是 success
之类的,在下面我们会用到它。
这里还有一个需要注意的是,有一行 app.config["SECRET_KEY"] = "rc498mt6848"
,app.config
是这个 app
的设定档,未来会有更舒服的方式去设定他,而 SECRET_KEY
是这个 app 的 secret key,会用来帮忙处理一些 session 的东西,像是此处的 flash
、登入的 session、未来会提到的 csrf_token 等等都会用到它,而有了它也可以反推前述的东西,因此不能外流,此处只是随便乱打,而且在开发模式,所以是没有关系的。
如果你在思考这个 flash
的东西到底去哪里了,可以看看 session
,但一样要记得先 import (from flask import session
)。应该可以看到类似 <SecureCookieSession {'_flashes': [('meow', 'meow')]}>
的内容。这个讯息还有一个特性是,在被前端使用过之後就会自动从 session
中消失,所以同样的讯息不会一直卡着。
接下来看到 index.html
,他在最一开始就 import,但是这并不是 python 的 import,他 import 的是一个 jinja 的档案,而这个档案在下方,我们等等就会看到。在 body
里面,我们呼叫刚刚引入的 display_msg
,并将 get_flashed_messages(with_categories=True)
作为其引数。这个函式就是用来抓 session
里面有哪些 flash
的讯息,後面的 with_categories
是说明要不要加上 category
,预设是 False
。他的表示方式是一个 list,以此处为例,有 with_categories=True
的结果会是 [("cat", "meow")]
、没有打或是设为 False
会得到 ["meow"]
。
最後看到 msg.jinja
,他就像是一个 module,里面有一个函式可以给别人引入。首先,就如同 if 和 for,他也需要 endmacro
,接下来我们可以看到他在 jinja 里面跑着非常接近 python 的语法,也可以发现刚刚设定的 category
被当成 class
来用。
在前面讲存取变数的时候,可能有人会好奇我们该如何设变数,因为之後用不太到,所以没有放在前面讲,我自己觉得不太会用到的原因是因为我们会用到的变数都已经在 render_template
中设定好了,剩下可能会用到的变数大概也只是 for 的时候会用到的区域变数,所以我个人觉得这个部分不太会使用,等等也不会放上范例。但我自己也真的有用过,像是想要把一些设定档交给 jinja 去对照,那就会先把设定档 import 进模板 (如何 import 等等会提到),然後给他一个变数名称作为简写之类的。
标题写着 set & with,代表这里有两种设定变数的方式,差异只在是全域变数还是区域变数而已。我们分开来说。
set
的用法是 {% set var=value %}
,非常简单。with
就比较麻烦一点,他建立了一个 scope,也就是说他创造的是区域变数。他的用法是 {% with var=value %}
,但在这个 scope 结束的时候要 {% endwith %}
,和前面提到的类似。虽然我们是在 python 里面用 jinja,但是在 jinja 中我们无法使用 python 的函式库。如果真的要使用的话,我们需要一点小技巧。但我自己是认为,能不要用就不要用。
python 里面有一个套件叫做 importlib
,我们可以在 render_template
後面加上 IMPORT=importlib.import_module
(import
在 jinja 里面是保留字,所以不能用),然後在模板里面就可以 set var=IMPORT('module')
,照着正常该怎麽用就可以了。
Configuration Handling - SECRET_KEY
How does the 'with' statement work in Flask (Jinja2)?
Whare are the difference between set and with in jinja
Import a Python module into a Jinja template?
<<: [Day4] Android - Kotlin笔记:RecyclerView Adapter - ListAdapter + DiffUtil
阿嬷都看得懂的元素容器与隐藏空格解法 昨天我们做出了满版横幅的粉红贴纸,今天要开始切中央的橘色贴纸与...
本篇文章同步发表在 HKT 线上教室 部落格,线上影音教学课程已上架至 Udemy 和 Youtu...
最初,Linux Kernel 的社群采用压缩档或是补丁的方式进行维护工作。一直到 2002 年,开...
大家好~ 接下来要把我们的 Echo bot 部署上 Amazon EC2 啦~ Amazon EC...
在我的架站经验中,我始终在「想要的功能与样式」和「网页载入速度」中不断拉扯! 不过,这样也好,促使我...