1+1=10

记记笔记,放松一下...

Python flask入门笔记(二)

Flask是一款轻量级的用python实现的web微框架,它基于Werkzeug WSGI工具包和Jinja2模板引擎。

前面初步认识了Wekzeug这一个WSGI工具包,那么Jinja又有什么神通...

Jinja

Jinja是一个python编写的web模板引擎,作者是来自Pocoo的Armin Ronacher,首次发布于2008年7月17日,采用BSD协议授权,目前最新版本是3.1.2。

安装

安装很简单,注意加上2。不然会遇到老版本的jinja。

1
pip install Jinja2

不然前面安装了Flask,默认已经装上Jinja2,所以不用太考虑

JInja内容挺多,详见:https://jinja.palletsprojects.com/en/3.1.x/templates/

此处仅通过小例子做些基本了解

例子一

Jinja做的事情很简单,先给它一个包含占位符的模板(模板加载),再提供包含变量的上下文给它,让其完成变量替换(模板渲染)。注意,变量定义格式{{vvvvv}}

模板可以在字符串中:

1
2
3
4
5
import jinja2

env = jinja2.Environment()
template = env.from_string('Hello {{ name }}!')
print(template.render(name='Debao'))

Jinja的核心组件时Environment这个类,此处构造时没有传入任何参数给它。

输出结果

1
Hello Debao!

这个例子,只完成字符串替换,实在没意思

例子二

模板一般都在文件中,文件名是什么后缀都无所谓。.htm,.latex,.txt,.jinja 都没关系。模板中的注释格式{# #}

比如,写一个模板:

1
2
3
{# hello.txt for example #}

Hello {{ name }}!

然后渲染它:

1
2
3
4
5
from jinja2 import Environment, FileSystemLoader

env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('hello.txt')
print(template.render(name='Debao'))

render的参数,可以是关键字参数,也可以是dict。上面最后一行,可以改为:

1
print(template.render({'name':'Debao'}))

例子三

只是变量替换意义不大,Jinja支持分支和循环等流程控制。

模板:

1
2
3
4
5
6
7
{# hello.txt for example #}

Hello.txt file

{% for account in accounts %}
Name: {{ account.name }} Email: {{ account.email }}
{% endfor %}

渲染:

1
2
3
4
5
6
7
8
9
from jinja2 import Environment, FileSystemLoader

accounts = [
        {'name': 'Debao', 'email': 'd@example.com'},
        {'name': 'Debao2', 'email': 'd2@example.com'},
        ]
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('hello.txt')
print(template.render({'accounts': accounts}))

注意:

  • 变量可以是python任意对象
  • for格式{% for in %} {% endfor %}

与此类似,if的格式如下:

1
2
3
4
5
{% if score > 80 %}
I'm happy to inform you that you did very well on today's test.
{% else %}
I'm sorry to inform you that you did not do so well on today's test.
{% endif %}

另外,for 和 if 的语句彼此可以嵌套使用。

例子四

看看block,单纯加上它对结果没什么影响,比如:

1
2
3
4
5
6
7
8
9
{# hello.txt for example #}

Hello.txt file

{% block content %}
{% for account in accounts %}
Name: {{ account.name }} Email: {{ account.email }}
{% endfor %}
{% endblock %}

但是,我们可以写另一个模板来覆盖对应的block:

1
2
3
4
5
6
7
8
{# hello2.txt for example #}
{% extends "hello.txt" %}

{% block content %}
{% for account in accounts %}
New Name: {{ account.name }} Email: {{ account.email }}
{% endfor %}
{% endblock %}

注意其中的extends。这样我们可以获取和渲染它了 env.get_template('hello2.txt')

除此之外,Jinja还有includeimport等扩展机制

  • include 用于包含其他文件内容
1
2
3
{% include 'header.html' %}
Body goes here.
{% include 'footer.html' %}
  • import 用于导入其他文件中的定义的宏macro
1
{% import 'forms.html' as forms %}

Flask模板

回归正题,看看Jinja模板在Flask中如何使用。

Flask需要将 Jinja模板放置在 templates 文件夹下,以便于使用render_template()进行渲染

这样(对应python模块):

1
2
3
/hello.py
/templates
    /hello.html

或者(对应python包)

1
2
3
4
/hello
    /__init__.py
    /templates
        hello.heml

例子

相比Jinja,这个就没多少新东西了...

  • 创建模板:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{# templates/base.html #}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>{{ title }}</title>
</head>

<body>
  <h1>Welcome to {{ title }}!</h1>
</body>
</html>
  • 写个程序:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('base.html', title='Flask')

if __name__ == '__main__':
    app.run('localhost', 8000)

参考

  • https://flask.palletsprojects.com
  • https://palletsprojects.com/p/jinja/
  • https://jinja.palletsprojects.com/en/3.1.x/templates/
  • https://en.wikipedia.org/wiki/Jinja_(template_engine)
  • https://realpython.com/primer-on-jinja-templating/