Flask【第四章】:Flask中的模板语言jinja2以及render_template的深度用法

Flask中的模板语言jinja2以及render_template的深度用法

一、jinja2

Flask中默认的模板语言是Jinja2.现在我们开始学习使用它

1. 先说一说jinja2模板中的流程控制。和Django中的一样

# Jinja2模板语言中的 for
{% for foo in g %}

{% endfor %}


#Jinja2模板语言中的 if
{% if g %}

{% elif g %}
    
{% else %}
    
{% endif %}

2. 我们定义几个数据用于传递到前端

STUDENT = {'name': 'Old', 'age': 38, 'gender': ''}

STUDENT_LIST = [
    {'name': 'Old', 'age': 38, 'gender': ''},
    {'name': 'Boy', 'age': 73, 'gender': ''},
    {'name': 'EDU', 'age': 84, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': 'Old', 'age': 38, 'gender': ''},
    2: {'name': 'Boy', 'age': 73, 'gender': ''},
    3: {'name': 'EDU', 'age': 84, 'gender': ''},
}

接下来,我们对这几种情况分别进行传递,并在前端显示成表格

1. 使用STUDENT字典传递至前端

后端代码:

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

STUDENT = {'name': 'Old', 'age': 38, 'gender': ''}

STUDENT_LIST = [
    {'name': 'Old', 'age': 38, 'gender': ''},
    {'name': 'Boy', 'age': 73, 'gender': ''},
    {'name': 'EDU', 'age': 84, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': 'Old', 'age': 38, 'gender': ''},
    2: {'name': 'Boy', 'age': 73, 'gender': ''},
    3: {'name': 'EDU', 'age': 84, 'gender': ''},
}

@app.route("/")
def index():
    return render_template("index.html",student = STUDENT)

app.run("192.168.13.69","5000",debug=True)
后端代码

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Old Boy EDU</title>
</head>
<body>
Welcome to Old Boy EDU
<div>{{ student }}</div>
<table border="1px">
    <tr>
        <td>{{ student.name }}</td>
        <td>{{ student["age"] }}</td>
        <td>{{ student.get("gender") }}</td>
    </tr>
</table>
</body>
</html>
前端代码

结果:

 

2.将STUDENT_LIST列表传入前端jinja2模板的操作:

后端代码:

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

STUDENT = {'name': 'Old', 'age': 38, 'gender': ''}

STUDENT_LIST = [
    {'name': 'Old', 'age': 38, 'gender': ''},
    {'name': 'Boy', 'age': 73, 'gender': ''},
    {'name': 'EDU', 'age': 84, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': 'Old', 'age': 38, 'gender': ''},
    2: {'name': 'Boy', 'age': 73, 'gender': ''},
    3: {'name': 'EDU', 'age': 84, 'gender': ''},
}

@app.route("/")
def index():
    return render_template("index.html",student = STUDENT_LIST)

app.run("192.168.13.69","5000",debug=True)
后端代码

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Old Boy EDU</title>
</head>
<body>
Welcome to Old Boy EDU
<div>{{ student }}</div>
<table border="1xp">
    {% for foo in student %}
        <tr>
            <td>{{ foo }}</td>
            <td>{{ foo.name }}</td>
            <td>{{ foo.get("age") }}</td>
            <td>{{ foo["gender"] }}</td>
        </tr>
    {% endfor %}
</table>
</body>
</html>
前端代码

结果:

这里我们可以看出如果是需要循环遍历的话,jinja2给我们的方案是:

{% for foo in student %}
        <tr>
            <td>{{ foo }}</td>
        </tr>
{% endfor %}

上述代码中的foo就是列表中的每一个字典,再使用各种取值方式取出即可。

 

3.STUDENT_DICT大字典传入前端jinja2模板

后端代码:

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

STUDENT = {'name': 'Old', 'age': 38, 'gender': ''}

STUDENT_LIST = [
    {'name': 'Old', 'age': 38, 'gender': ''},
    {'name': 'Boy', 'age': 73, 'gender': ''},
    {'name': 'EDU', 'age': 84, 'gender': ''}
]

STUDENT_DICT = {
    1: {'name': 'Old', 'age': 38, 'gender': ''},
    2: {'name': 'Boy', 'age': 73, 'gender': ''},
    3: {'name': 'EDU', 'age': 84, 'gender': ''},
}

@app.route("/")
def index():
    return render_template("index.html",student = STUDENT_DICT)

app.run("192.168.13.69","5000",debug=True)
后端代码

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Old Boy EDU</title>
</head>
<body>
Welcome to Old Boy EDU
<table>
    {% for foo in student %}
        <tr>
            <td>{{ foo }}</td>
            <td>{{ student.get(foo).name }}</td>
            <td>{{ student[foo].get("age") }}</td>
            <td>{{ student[foo]["gender"] }}</td>
        </tr>
    {% endfor %}
</table>
</body>
</html>
前端代码

在遍历字典的时候,foo其实是相当于拿出了字典中的key

结果:

 

4.利用"**{}"字典的方式传递参数

后端代码:

@app.route("/allstudent")
def all_student():
    return render_template("all_student.html", **{"student":STUDENT ,
                           "student_list" : STUDENT_LIST,
                           "student_dict": STUDENT_DICT})

 

二、jinja2的高阶用法

jinja2模板语言为我们提供了很多功能,接下来看一下它有什么高级的用法。

1. safe:

说明:安全标签字符串

先看一下例子:

后端代码:

from flask import Flask
from flask import render_template

app = Flask(__name__)

@app.route("/")
def index():
    tag = "<input type='text' name='user' value='DragonFire'>"
    return render_template("index.html",tag=tag)

app.run("192.168.13.69",5000)
后端代码

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{ tag }}
</body>
</html>
前端代码

直接运行代码访问,看页面是什么

 

这似乎和我们想要结果不太一样,有两种解决方案:

第一种:从前端入手

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{ tag | safe}}  <!--  加上个 \  管道符,然后 safe  -->
</body>
</html>

前端代码

第二种:从后端入手

from flask import Flask
from flask import render_template
from flask import Markup  # 导入 flask 中的 Markup 模块

app = Flask(__name__)


@app.route("/")
def index():
    tag = "<input type='text' name='user' value='DragonFire'>"
    markup_tag = Markup(tag)  # Markup帮助咱们在HTML的标签上做了一层封装,让Jinja2模板语言知道这是一个安全的HTML标签
    print(markup_tag,
          type(markup_tag))  # <input type='text' name='user' value='DragonFire'> <class 'markupsafe.Markup'>
    return render_template("index.html", tag=markup_tag)


app.run("0.0.0.0", 5000, debug=True)

两种得到的效果是一样的

 

2. 在jinja2中执行python函数(模板中执行函数)

首先在文件中定义一个函数

后端代码:

from flask import Flask
from flask import render_template
from flask import Markup  # 导入 flask 中的 Markup 模块

app = Flask(__name__)

#定义一个函数,把它传递给前端
def a_b_sum(a,b):
    return a+b

@app.route("/")
def index():
    return render_template("index.html", tag=a_b_sum)


app.run("0.0.0.0", 5000, debug=True)

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{ tag }}
    <br>
    {{ tag(99,1) }}
</body>
</html>

显示结果:

看到结果就是,函数加()执行得到结果

还可以定义全局函数,无需后端传递给前端,jinja2直接就可以执行的函数

后端代码:

from flask import Flask
from flask import render_template
from flask import Markup  # 导入 flask 中的 Markup 模块

app = Flask(__name__)


@app.template_global()  # 定义全局模板函数
def a_b_sum(a, b):
    return a + b


@app.template_filter()  # 定义全局模板函数
def a_b_c_sum(a, b, c):
    return a + b + c


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


app.run("0.0.0.0", 5000, debug=True)

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{ a_b_sum(99,1) }}
    <br>
    {{ 1 | a_b_c_sum(197,2) }} #将管道符前面的运算结果也就是1 当做管道符后面的函数的第一个参数
</body>
</html>

两个函数的调用方式不太一样

尤其是@app.template_filter() 它的调用方式比较特别,这是两个Flask中的特殊装饰器

 

3. jinja2模板复用block

如果我们前端页面有大量重复页面,没必要每次都写,可以使用模板复用的方式复用模板

前端代码:

index.html文件中的内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Welcome OldboyEDU</h1>
    <h2>下面的内容是不一样的</h2>
    {% block content %}

    {% endblock %}
    <h2>上面的内容是不一样的,但是下面的内容是一样的</h2>
    <h1>OldboyEDU is Good</h1>
</body>
</html>
index.html

login.html文件中的内容

{% extends "index.html" %}
{% block content %}
    <form>
        用户名:<input type="text" name="user">
        密码:<input type="text" name="pwd">
    </form>
{% endblock %}
login.html

home.html文件中的内容

{% extends "index.html" %}
{% block content %}
    <h1>欢迎来到老男孩教育</h1>
{% endblock %}

后端代码:

from flask import Flask
from flask import render_template

app = Flask(__name__)


@app.route("/login")
def login():
    return render_template("login.html")


@app.route("/home")
def home():
    return render_template("home.html")


app.run("0.0.0.0", 5000, debug=True)

然后我们看一下效果:

大概就是这样一个效果了,在这两个页面中,只有block中的内容发生了变化,其他位置完全一样。

 

4. jinja2模板语言的模块引用 include

login.html 文件中的内容:

<form>
    用户名:<input type="text" name="user">
    密码:<input type="text" name="pwd">
</form>

index.html 文件中的内容

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>Welcome OldboyEDU</h1>
    <h2>下面的内容是不一样的</h2>
    {% include "login.html" %}
    <h2>上面的内容是不一样的,但是下面的内容是一样的</h2>
    <h1>OldboyEDU is Good</h1>
</body>
</html>
复制代码

后端代码:

复制代码
from flask import Flask
from flask import render_template

app = Flask(__name__)


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


app.run("0.0.0.0", 5000, debug=True)
复制代码

看到的结果

这就是将 login.html 当成一个模块,加载到 index.html 页面中

 

 

5. jinja2模板语言中的宏定义

前端代码:

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>Welcome OldboyEDU</h1>

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

<h2>在下方是使用宏来生成input标签</h2>

{{ type_text("one","text") }}
{{ type_text("two","text") }}

</body>
</html>
复制代码

宏定义一般情况下很少应用到,但是要知道有这么个概念

 

posted @ 2019-01-07 19:46  重启试试  阅读(462)  评论(0编辑  收藏  举报