[python][flask] Jinja 模板入门

Flask 和 Django 附带了强大的 Jinja 模板语言。

对于之前没有接触过模板语言的人来说,这类语言基本上就是包含一些变量,当准备渲染呈现 HTML 时,它们会被实际的值替换。

这些变量放在标记或分隔符之前。例如:Jinja 模板使用 {% ... %} 表示循环, {{ ... }} 表示一个表达式运算结果返回。

Jinja 模板其实是 html 文件。一般情况下放在 Flask 工程的 /templates 目录下

1、快速体验

跑下面的各种 demo 之前,确保你已经安装了 Jinja (pip install jinja2)

>>> from jinja2 import Template
>>> t = Template("Hello {{ something }}!")
>>> t.render(something="World")
u'Hello World!'

>>> t = Template("My favorite numbers: {% for n in range(1,10) %}{{n}} " "{% endfor %}")
>>> t.render()
u'My favorite numbers: 1 2 3 4 5 6 7 8 9 '

这个 demo 展示了模板中的变量(表达式)是如何最终被替换和渲染的。

2、Flask 最小 DEMO

整个的参考代码可以在这里获得:HERE

不过博主建议按照下面步骤一步步来:

1)安装 flask

➜  pip install flask

2)创建工程目录结构:

➜  mkdir flask_example
➜  cd flask_example
➜  mkdir templates
➜  cd ..

➜  touch run.py
➜  touch requirements.txt

3)编写 run.py

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

@app.route("/")
def template_test():
    return render_template('template.html', my_string="Wheeeee!", my_list=[0,1,2,3,4,5])

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

这里,我们创建了一个 / 路由,当我们访问服务器根路由时,会通过 render_templatetemplate.html 渲染,其中 my_stringmy_list 就是准备传给模板的实际的值。

4)编写 template.html 模板

在 templates 目录下,创建一个 template.html:


    Flask Template Example

      .container {
        max-width: 500px;
        padding-top: 100px;
      }

      My string: {{my_string}}
      Value from the list: {{my_list[3]}}
      Loop through the list:

        {% for n in my_list %}
        {{n}}
        {% endfor %}

5)运行观察效果

➜  python run.py

效果如下:

[python][flask] Jinja 模板入门

可以看到,将模板中的 my_string、my_list[3] 替换掉了,并且用 for 循环语句,生成了一个 list。

3、模板继承

模板通常利用继承,继承包括定义所有后续子模板基本结构的单个基础模板。您可以使用标记 {% extends %}{% block %} 来实现继承。

这样做的用例很简单:随着应用程序的增长,以及您继续添加新模板,您将需要保持公共代码(如HTML导航栏、Javascript库、CSS样式表等)同步,这可能需要大量工作。使用继承,我们可以将这些公共部分移动到父/基模板,这样我们就可以创建或编辑这样的代码一次,所有子模板都将继承该代码。

注意:您应该总是尽可能多地向基本模板添加重复代码,以节省将来的时间,这将远远超过初始时间投资。

让我们给我们的 DEMO 增加模板:

1)创建基础模板(保存为 layout.html


    Flask Template Example

      .container {
        max-width: 500px;
        padding-top: 100px;
      }
      h2 {color: red;}

      This is part of my base template

      {% block content %}{% endblock %}

      This is part of my base template

你注意到 {%block%} 标记了吗?这定义了子模板可以填充的块或区域。此外,也可实现覆盖的作用。

2)用模板更新 template.html:

{% extends "layout.html" %}
{% block content %}
   This is the start of my child template

  My string: {{my_string}}
  Value from the list: {{my_list[3]}}
  Loop through the list:

    {% for n in my_list %}
    {{n}}
    {% endfor %}

   This is the end of my child template
{% endblock %}

这样 layout.html 模板中的 content 块就会被 template.html 中的新定义给替换掉,最终效果如下:

[python][flask] Jinja 模板入门

那么,我们就可以通过修改 layout.html 给其添加通用导航栏了:(将下列代码插入到 layout.html<body></body> 标签之后)


        Toggle navigation

      Jinja!

        Link
        Link

        Submit

        Link

          Dropdown

            Action
            Another action
            Something else here

            Separated link

现在,从基础扩展的每个子模板都将具有相同的导航栏。借用Java哲学的一句话:”Write once, use anywhere.”

[python][flask] Jinja 模板入门

4、Super Blocks

如果需要从基础模板渲染块,使用 super block:

{{ super() }}

给基础模板增加一个页脚:


 ...

  This is part of my base template

    {% block footer %}
      Watch! This will be added to my base and child templates using the super powerful super block!

    {% endblock %}

...

此时,我们可以给 template.html 增加 super block,从而实现子模板复用父模板中的块:

{% extends "layout.html" %}
{% block content %}
   This is the start of my child template

  My string: {{my_string}}
  Value from the list: {{my_list[3]}}
  Loop through the list:

    {% for n in my_list %}
    {{n}}
    {% endfor %}

   This is the end of my child template
  {% block footer %}
  {{super()}}
  {% endblock %}
{% endblock %}

效果如下:

[python][flask] Jinja 模板入门

super block 用于模块共享父模块的 block,当然还有一些高级玩法,比如下面的例子:

父模板:

{% block heading %}
  {% block page %}{% endblock %} - Flask Super Example
{% endblock %}

子模板:

{% block page %}Home{% endblock %}
{% block heading %}
  {{ super() }}
{% endblock %}

这样当访问子模块时,会拼接一个 <h1>Home - Flask Super Example</h1> 字段。发现没,我们通过这样的方法,实现了标题的继承(有一定的继承,也有一定的子模块自己的信息)。

回归正轨,对于更新标题,我们这里这样设计(修改 template.html 中的两行代码)

{% block title %}{{title}}{% endblock %}
...

{% block page %}{{title}}{% endblock %}

这样我们可以通过 python 进来直接修改标题了(修改 run.py):

@app.route("/")
def template_test():
    return render_template(
        'template.html', my_string="Wheeeee!",
        my_list=[0,1,2,3,4,5], title="Home")

5、Macros

在 Jinja 中,我们可以使用宏来抽象常用的代码段,这些代码段被反复使用以避免重复。例如,通常会在导航栏上突出显示当前页面的链接(活动链接)。否则,我们必须使用 if/elif/else 语句来确定活动链接。使用宏,我们可以将这些代码抽象成一个单独的文件。

新增一个 macros.html 文件:

{% macro nav_link(endpoint, name) %}
{% if request.endpoint.endswith(endpoint) %}
  {{name}}
{% else %}
  {{name}}
{% endif %}
{% endmacro %}

这里,我们使用了 Flask 的 request object(Jinja 的默认一部分),用来检查请求端点,然后将活动 class 分配给该端点。

使用基础模板中的nav navbar nav类更新无序列表:


  {{ nav_link('home', 'Home') }}
  {{ nav_link('about', 'About') }}
  {{ nav_link('contact', 'Contact Us') }}

此外,请确保在模板顶部添加导入: {% from "macros.html" import nav_link with context %}

最后,让我们向控制器添加三个新端点:

@app.route("/home")
def home():
    return render_template(
        'template.html', my_string="Wheeeee!",
        my_list=[0,1,2,3,4,5], title="Home")

@app.route("/about")
def about():
    return render_template(
        'template.html', my_string="Wheeeee!",
        my_list=[0,1,2,3,4,5], title="About")

@app.route("/contact")
def contact():
    return render_template(
        'template.html', my_string="Wheeeee!",
        my_list=[0,1,2,3,4,5], title="Contact Us")

刷新页面。测试顶部的链接。当前页面是否突出显示?(每次点击 Home, About, Contact Us,浏览器会自动跳转到对应的 url,并加载页面)

6、自定义过滤器

Jinja 使用过滤器修改变量,主要用于格式化目的。

这有个例子;

{{ num | round }}

这将使 num 变量四舍五入。因此,如果我们将参数 num=46.99 传递到模板中,那么将输出47.0。(把大括号中的语句当做 shell,就明白了,竖线是传递作用,round是个过滤器,这里是所有的过滤器)

再来个例子:

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

可以给 list 数组中的变量加个逗号。

其实,除了自带的过滤器,我们也可以自定义:

1)在 run.py 的所有函数前增加 app = Flask(__name__) 用于创建一个 app
2)增加一个 datetimefilter 函数,并将其注册到 app 的过滤器

@app.template_filter() # 声明,这是个过滤器
def datetimefilter(value, format='%Y/%m/%d %H:%M'):
    """Convert a datetime to a different format."""
    return value.strftime(format)

app.jinja_env.filters['datetimefilter'] = datetimefilter

3)这样,我们在子模板中插入如下代码:

Current date/time: {{ current_time | datetimefilter }}

4)最后,只要在 python 中将时间传入模板即可:

current_time = datetime.datetime.now()

5)效果如下:

[python][flask] Jinja 模板入门

7、结论

这样,就送大家快速入门了 Jinja,源码:https://github.com/mjhea0/thinkful-mentor/tree/master/python/jinja/flask_example

参考链接

[1]. 本文源码
[2]. Primer on Jinja Templating(本文翻译并参考这篇)
[3]. Flask 官方文档
[4]. 真正搞明白Python中Django和Flask框架的区别
[5]. Flask 主页
[6]. 一个 Soft UI Dashboard – Free Jinja Template
[7]. Appseed 这个网站有很多 Flask 模板
[8]. Nginx 服务器 SSL 证书安装部署
[9]. python django web 开发 —— 15分钟送到会用(只能送你到这了)

: 在学习 Django 和 Flask 等 Python 的服务器框架时,都需要了解模板的概念,这篇能够快速带你入门…

[python][flask] Jinja 模板入门

Original: https://www.cnblogs.com/zjutlitao/p/16127063.html
Author: beautifulzzzz
Title: [python][flask] Jinja 模板入门

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/585655/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Docker Manager for Docker Swarm deploy

    一、Swarm概述 Swarm是Docker公司在2014年12月初发布的一套较为简单的工具,用来管理Docker集群,它将一群Docker宿主机变成一个单一的,虚拟的主机。Swa…

    Linux 2023年6月14日
    0117
  • Nginx服务的搭建与配置

    Nginx服务的搭建与配置 一、关闭防火墙并安装epel源 1、关闭selinux ①修改selinux的配置文件 [root@localhost ~]# vim /etc/sel…

    Linux 2023年6月7日
    0122
  • Flink Table Api & SQL 初体验,Blink的使用

    概述 Flink具有Table API和SQL-用于统一流和批处理。 Table API是用于Scala和Java的语言集成查询API,它允许以非常直观的方式组合来自关系运算符(例…

    Linux 2023年6月7日
    0129
  • Redisson 分布式锁实战与 watch dog 机制解读

    源地址:https://www.cnblogs.com/keeya/p/14332131.html Original: https://www.cnblogs.com/SimonH…

    Linux 2023年5月28日
    0123
  • html2canvas生成并下载图片

    html <div id="downChart"> div> jq new html2canvas(document.getElementBy…

    Linux 2023年6月7日
    093
  • 防止shell script多次运行

    防止shell script多次运行 一个思路是在script初期检测系统中是否存在同名进程。 if [ ps -ef | grep "test.sh" | g…

    Linux 2023年5月28日
    089
  • Docker清理日志脚本

    Docker清理日志脚本 #!/bin/sh 此脚本为日常清理docker日志 docker 容器的路劲日志为 /var/lib/docker/containers/ 下-json…

    Linux 2023年6月8日
    094
  • 《拉钩课程 – 重学操作系统 – Linux 指令入门》

    1、进程是什么?进程是应用的执行副本。应用的可执行文件是放在文件系统里,把可执行文件启动,就会在操作系统里(具体来说是内存中)形成一个应用的副本,这个副本就是进程。 2、Linux…

    Linux 2023年5月27日
    0116
  • Linux系统查看hosts配置与dns域名配置

    ;gutter:true;方法1:for i incat /etc/hosts | grep -v ^$ | grep -v “127.0.0.1” | g…

    Linux 2023年6月13日
    092
  • k8s/kubeadm 生产环境高可用集群部署

    kubeadm 生产环境集群部署 基本环境配置 kubeadm 安装方式自 1.14 版本以后,安装方法几乎没有任何变化,此文档可以尝试安装最新的 k8s 集群, centos 采…

    Linux 2023年6月14日
    0102
  • Shell脚本编程中的几个问题

    条件语句 正确的写法: if [ $1 = "-f" ] #注意这里,前后方括号和中间的内容之间必须有空格! then commands fi 错误的写法: i…

    Linux 2023年6月14日
    086
  • 【C++基础】变量、常量、关键字、标识符命名

    四个步骤: 创建项目 创建文件 编写代码 运行程序 写代码前的框架: #include using namespace std; int main() { system(&quot…

    Linux 2023年6月13日
    0102
  • 条件分支

    条件分支 if-else-fi [root@node1 test]# vim if.sh #!/bin/bash amswer=30 if [ $1 -gt $answer ];t…

    Linux 2023年6月11日
    081
  • 脚本安装lamp

    脚本安装lamp [root@localhost ~]# mkdir lamp [root@localhost ~]# cd lamp/ [root@localhost lamp]…

    Linux 2023年6月6日
    0133
  • 从前端走向后端

    每次过年回老家聚会,遇到不熟悉的亲戚朋友,经常被问到职业是什么。一开始,我总是很认真的回答这个问题,结果常常引出一番尴尬的问答。 &#x201C;&#x4F60;&…

    Linux 2023年6月6日
    0105
  • 设计模式——创建型设计模式

    创建型设计模式 争对 &#x5BF9;&#x8C61;/&#x7C7B;创建时的优化 工厂方法模式(了解) 通过定义顶层抽象工厂类,通过继承的方式,针对于每…

    Linux 2023年6月7日
    0102
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球