Python jinja2 基础知识

@

jinja2原理

Flask 的render_template默认使用了jinja2的模板引擎渲染页面

demo.py

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def demo():
    return render_template('demo.html')


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

templates/demo.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<h1>你好,</h1>
</body>
</html>

渲染出的html是这样的

这和下面的代码的效果没有什么区别

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def demo():
    html = """"
        <!doctype html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport"
                  content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
            <meta http-equiv="X-UA-Compatible" content="ie=edge">
            <title>Document</title>
        </head>
        <body>
        <h1>你好,</h1>
        </body>
        </html>
    """
    return html


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

而且也能传参数

demo.py

from flask import Flask

app = Flask(__name__)


@app.route('/')
def demo():
    with open('templates/demo.html', 'r', encoding='utf-8') as file:
        html = file.read()
        html = html.replace('{{ your_name }}', 'pineapple')
    return html


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

templates/demo.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<h1>你好,{{ your_name }}</h1>
</body>
</html>

渲染结果如下所示:

在这里插入图片描述

这样就简单实现了前端html和后端python代码的交互,这就是jinja2和其他一些模板引擎的原理!

jinja2基本语法

  • {% ...%}用于循环或判断语句。

  • {{...}}用于表达式的值的引用。

  • {# ...#}用于模板引擎的注释,如果注释中存在模板引擎的语法,那么使用将不被模板引擎认为是注释,注释中的语法将被执行。此时请使用{##}进行注释。

普通传值

语法:{{ python表达式 }}

templates/demo.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div {
            width: 400px;
            height: 200px;
            border: solid 2px red;
            text-align: center;
            padding: 20px;
            line-height: 40px
        }
    </style>
</head>
<body>
<div>
    <span>你的登录账号为:{{ session.get('username') }}</span><br>
    <span>这篇文章的标题:{{ article.title }}</span><br>
    <span>文章的阅读次数:{{ article.count + 1 }}</span><br>
</div>
</body>
</html>

demo.py

import os

from flask import Flask, render_template, session

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)


@app.route('/')
def demo():
    session['username'] = 'Pineapple'
    article = {
        'title': 'Flask jinja2模板',
        'count': 9999
    }
    return render_template('demo.html', session=session, article=article)


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

渲染结果:

在这里插入图片描述

jinja2的模板里,字典可以用dict.key的方式获取值

条件语句

语法

{% if %}

{% elif %}

{% else %}

{% endif %}

templates/demo.html继续添加

{% if article.count % 2 == 0 %}
<span>{{ article.count }}可以被2整除,是个偶数</span>
{% else %}
<span>{{ article.count }}不可以可以被2整除,是个奇数</span>
{% endif %}
在这里插入图片描述

循环语句

语法

{% for %}

{% endfor %}

templates/demo.html继续添加

{% for i in range(5) %}
<span>第{{ i }}次</span><br>
{% endfor %}
在这里插入图片描述

初始化变量

在jinja2模板中,用set关键字初始化变量

{% set loop = 6 %}
{% for i in range(loop) %}
<span>第{{ i }}次</span><br>
{% endfor %}
在这里插入图片描述

过滤器

https://jinja.palletsprojects.com/en/2.11.x/templates/#id11
https://jinja.palletsprojects.com/en/2.11.x/templates/#list-of-builtin-filters

过滤器其实就是函数,以 | 分割,左边的输出作为右边过滤器的参数输入,有点类似于Linux的管道

内置过滤器

在这里插入图片描述

举几个栗子

safe

safe(value)

将值标记为安全,这意味着在具有自动转义启用后,此变量将不会被转义。

先看看不加safe

templates/demo.html 添加

{{ red_font }}

demo.py 添加

red_font = """
        <span style="color: red">这是一段红色的字</span>
    """
return render_template('demo.html', session=session, article=article, red_font=red_font)

可以看到它是以普通字符串的形式展示在页面上的

加上过滤器后

{{ red_font | safe }}

所以这个safe还是很有用地,之后向 Echarts js传数据也会用到它

truncate

truncate(s, length=255, killwords=False, end='...', leeway=None)

返回字符串的截断副本。 长度已指定 第一个参数默认为 255。 如果第二参数是 true过滤器将剪切文本的长度。 除此以外 它将丢弃最后一个单词。 如果文字是事实截断后会附加省略号( "...")。 如果你想要一个 与 省略号不同的省略号 "..."您可以使用的 第三个参数。 仅超出长度公差的字符串 第四个参数中给出的空白将不被截断。

{{ "foo bar baz qux"|truncate(9) }}
    -> "foo..."
{{ "foo bar baz qux"|truncate(9, True) }}
    -> "foo ba..."
{{ "foo bar baz qux"|truncate(11) }}
    -> "foo bar baz qux"
{{ "foo bar baz qux"|truncate(11, False, '...', 0) }}
    -> "foo bar..."

如果killwords=True,那么返回的字符串的长度为指定的长度 + end长度:length + len(end)

这个truncate还是挺复杂的,不明白老外为啥非得这么搞,就不能像python里的切片一样吗?

更详细的解释请看这位同志:https://blog.csdn.net/yueguangmanong/article/details/85196199

调用自定义函数

在模板中调用python中的函数,主要又两种方法

装饰器

使用上下文处理器context_processor

这种调用方式,准确的说不是调用函数,而是调用返回值的参数,且返回值必须是字典形式,也可以说是json格式

dem.py

@app.context_processor
def func():
    result1 = {'1': 'Python', '2': 'Linux', '3': 'Java'}
    result2 = [1, 2, 3, 4, 5, 6]
    return dict(result1=result1, result2=result2)

templates/demo.html

{{ result1 }}
{{ result2 }}
{{ result1['1'] }}

渲染结果

在这里插入图片描述

这种方式如果想要传参,得使用两层闭包

demo.py

@app.context_processor
def func():
    def func1(args1):
        result = {'1': 'Python', '2': 'Linux', '3': 'Java'}
        return result[args1]

    return dict(func1=func1)

tmeplates/demo.html

{{ func1('1') }}

渲染结果

在这里插入图片描述

全局注册

在全局jinja_env中注册自定义函数

demo.py

def func():
    result = {'1': 'Python', '2': 'Linux', '3': 'Java'}
    return result


app.jinja_env.globals.update(func=func)

templates/demo.html

{{ func() }}

注意这时是要加小括号()的,不然得到的将是函数的地址,而不是调用函数

渲染结果

在这里插入图片描述

这种方式的话,传参数会变得简单些

def func(args):
    result = {'1': 'Python', '2': 'Linux', '3': 'Java'}
    return result[args]


app.jinja_env.globals.update(func=func)
{{ func('2') }}

渲染结果

在这里插入图片描述

调用自定义过滤器

过滤器其实就是一种特殊的函数,将|前的值作为|后的函数第一个参数,函数返回值为最终结果

也是有两个方法,不过都大差不差

装饰器

调用模板过滤器template_filter,参数为过滤器名,和函数名并无关系

demo.py

@app.template_filter('my_len')
def my_len(s):
    return len(s)

templates/demo.html

{{ "Hello, how are you ? " | my_len }}

渲染结果

在这里插入图片描述

全局注册

与自定义函数一样,同样是注册到jinja_env里

def my_len(s):
    return len(s)


app.jinja_env.filters.update(my_len=my_len)

渲染结果和上面一样,不演示了。

posted @ 2022-04-07 11:18  王舰  阅读(627)  评论(0编辑  收藏  举报