Web框架 Flask 之 Jinja2 模板引擎

文章目录

    • 渲染模板
    • 传递参数到模板中
    • 过滤器
    • 模板语法
      • 变量
      • 注释
      • 控制结构
        • for
        • if
    • 模板继承
    • 包含
    • 参考资料

渲染模板

在 Python 内部生成 HTML 不好玩,且相当笨拙。因为你必须自己负责 HTML 转义,来确保应用的安全。因此,Flask 自动为您配置 Jinja2 模板引擎

使用 render_template() 方法可以渲染模板,你只需要提供模板名称和需要作为参数传递给模板的变量就可以了

下面是一个简单的模板渲染的例子:

from flask improt render_template

@app.route("/hello/")
def view():
    return render_template("index.html")

flask 将尝试在 templates 文件夹中寻找 HTML 文件。因此,如果你的应用是一个模块,那么模板文件夹应该在模块同级目录下

/run.py
/templates
    /index.html

传递参数到模板中

(1) 变量传值

return render_template("index.html", name="zong", age=18, hobby=["唱歌","游泳"])
<body>
<p>姓名: {{ name }}p>
<p>年龄: {{ age }}p>
<p>爱好: {{ hobby }}p>
body>

(2) 字典传值

dct = {
    "name": "zong",
    "age": 18,
    "hobby": ["唱歌","游泳"]
}
return render_template("index.html", dct=dct)
<body>
<p>姓名: {{ dct.name }}p>
<p>年龄: {{ dct.age }}p>
<p>爱好: {{ dct.hobby }}p>
body>

过滤器

变量可以通过过滤器修改,过滤器和变量用管道符号 | 分割,并且也可以用圆括号传递可选参数。多个过滤器可以链式调用,前一个多滤器的输出会被作为后一个过滤器的输入

例如 {{ name|striptags|title }} 会移除 name 中所有 HTML 标签并且改写为标题样式的大小写格式

过滤器接受带圆括号的参数,如同函数调用,如 把一个列表用逗号链接起来

{{ list|join(',') }}

常用过滤器:

过滤器 示例 描述
striptags bq|striptags 去除标签
reverse test|reverse 字符串反转
default url|default("***") 默认值
safe bq|safe 将值标记为安全,不再自动转义
length [1,2,3]|length 列表长度
sum [1,2,3]|sum 列表求和
sort [1,2,3]|sort 列表排序

自定义过滤器:

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

(1) add_temp_filter()

def my_filter(test):
    return "***"

app.add_temp_filter(my_filter,"my_filter")

可以给过滤器指定一个名字,如果不指定,默认为函数名

(2) @app.template_filter

@app.template_filter("mf")
def my_filter(args):
    return "***"

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

模板语法

模板仅仅是文本文件,可以生成任何基于文本的格式(HTML,XML,CSV等)。它并没有特定的扩展名,.html.xml 都是可以的

模板包含 变量表达式,这两者在模板求值的时候会被替换为值。模板中还有标签,控制模板的逻辑。Jinja2 模板语法的大量灵感来自 Django 和 Python

下面是一个最小的模板:


<html">
<head>
    <title>testtitle>
head>
<body>
    <ul id="navigation">
    {% for item in navigation %}
        <li><a href="{{ item.href }}">{{ item.caption }}a>li>
    {% endfor %}
    ul>

    <h1>My Webpageh1>
    {{ a_variable }}
body>
html>

这里有两种分隔符 {% ... %}{{ ... }},前者用于执行诸如 for 循环 或 赋值的语句,后者把表达式的结果打印到模板上

变量

将变量传到到模板后,可以使用 . 来访问变量的属性,作为替代,也可以使用下标语法 [],下面几行效果是一样的

{{ foo.bar }}
{{ foo['bar'] }}

注释

要把模板中一行的部分注释掉,默认使用 {# ... #} 注释语法

控制结构

控制结构指的是所有的可以控制程序流的东西 --条件(if/elif/else)、for循环等,控制结构在默认语法中以 {% ... %} 块的形式出现

for

遍历序列中的每项

<ul>
{% for user in users %}
    <li>{{ user.username|e }}</li>
{% endfor %}
</ul>

在一个 for 循环块中你可以访问这些特殊的变量

变量 描述
loop.index 当前循环迭代的次数 (从 1 开始)
loop.index0 当前循环迭代的次数 (从 0 开始)
loop.revindex 到循环结束需要迭代的次数(从 1 开始)
loop.revindex0 到循环结束需要迭代的次数(从 0 开始)
loop.first 如果是第一次迭代,为 True
loop.last 如果是最后一次迭代,为 True
loop.length 序列中的项目数
loop.cycle 在一串序列间期取值的辅助函数。见下面的解释

在 for 循环中,可以使用特殊的 loop.cycle 辅助函数,伴随循环在一个字符串 / 变量列表中周期取值

{% for row in rows %}
    <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li>
{% endfor %}

与 python 中不同,模板中的循环不能 break 或 continue

if

{% if a == 1 %}
    a == 1
{% elif a == 2 %}
    a == 2
{% else %}
    a != 1 && a != 2
{% endif %}

模板继承

Jinja 中最强大的部分就是模板继承,可以把一写公共的代码放在父模块中,避免每个模块写同样的代码。同时父模板中提前在可能更改的地方定义好接口,方便子模板进行修改!

基本的父模板

这个模板,我们习惯性叫做 base.html,定义了一个简单的 HTML 骨架文档


<html>
<head>
    {% block head %}
    <link rel="stylesheet" href="style.css" />
    <title>
        {% block title %}{% endblock %} - My Webpage
    title>
    {% endblock %}
head>
<body>
    <div id="content">
        {% block content %}{% endblock %}
    div>
    
    <div id="footer">
        {% block footer %}{% endblock %}
    div>
body>
html>

所有的 block 标签告诉模板引擎子模板可以覆盖模板中的这些部分

{% block 接口名 %}

{% endblock %}

子模板

# 继承父模板
{% extends "base.html" %}

# 覆盖父模板 title 块的内容
{% block title %}Index{% endblock %}

{% block head %}
    {{ super() }}
    <style type="text/css">
        .important { color: #336699; }
    </style>
{% endblock %}

{% block content %}
    <h1>Index</h1>
    <p class="important">
      Welcome on my awesome homepage.
    </p>
{% endblock %}

包含

include 语句用于包含一个模板,并在当前命名空间中返回那个文件的内容渲染结果


<ul>
    <li>Pythonli>
    <li>Javali>
    <li>PHPli>
    <li>GOli>
    <li>C++li>
ul>



{% include "cs.html" %}


{% include "cs.html" ignore missing %}

一个模板中可以多次使用 include 语句
include 可以和 模板继承同时使用

参考资料

Jinja2 中文手册

你可能感兴趣的:(Flask)