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:

<!DOCTYPE html>
<html>
  <head>
    <title>Flask Template Example</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" media="screen">
    <style type="text/css">
      .container {
        max-width: 500px;
        padding-top: 100px;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <p>My string: {{my_string}}</p>
      <p>Value from the list: {{my_list[3]}}</p>
      <p>Loop through the list:</p>
      <ul>
        {% for n in my_list %}
        <li>{{n}}</li>
        {% endfor %}
      </ul>
    </div>
    <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
  </body>
</html>

5)运行观察效果

➜  python run.py

效果如下:

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

3、模板继承

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

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

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

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

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

<!DOCTYPE html>
<html>
  <head>
    <title>Flask Template Example</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" media="screen">
    <style type="text/css">
      .container {
        max-width: 500px;
        padding-top: 100px;
      }
      h2 {color: red;}
    </style>
  </head>
  <body>
    <div class="container">
      <h2>This is part of my base template</h2>
      <br>
      {% block content %}{% endblock %}
      <br>
      <h2>This is part of my base template</h2>
    </div>
    <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
  </body>
</html>

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

2)用模板更新 template.html:

{% extends "layout.html" %}
{% block content %}
  <h3> This is the start of my child template</h3>
  <br>
  <p>My string: {{my_string}}</p>
  <p>Value from the list: {{my_list[3]}}</p>
  <p>Loop through the list:</p>
  <ul>
    {% for n in my_list %}
    <li>{{n}}</li>
    {% endfor %}
  </ul>
  <h3> This is the end of my child template</h3>
{% endblock %}

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

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

<nav class="navbar navbar-inverse" role="navigation">
  <div class="container-fluid">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="/">Jinja!</a>
    </div>

    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
      </ul>
      <form class="navbar-form navbar-left" role="search">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

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

4、Super Blocks

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

{{ super() }}

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

<body>
<div class="container">
 ...
  <h2>This is part of my base template</h2>
  <br>
  <div class="footer">
    {% block footer %}
      Watch! This will be added to my base and child templates using the super powerful super block!
      <br>
      <br>
      <br>
    {% endblock %}
  </div>
</div>
...

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

{% extends "layout.html" %}
{% block content %}
  <h3> This is the start of my child template</h3>
  <br>
  <p>My string: {{my_string}}</p>
  <p>Value from the list: {{my_list[3]}}</p>
  <p>Loop through the list:</p>
  <ul>
    {% for n in my_list %}
    <li>{{n}}</li>
    {% endfor %}
  </ul>
  <h3> This is the end of my child template</h3>
  {% block footer %}
  {{super()}}
  {% endblock %}
{% endblock %}

效果如下:

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

父模板:

{% block heading %}
  <h1>{% block page %}{% endblock %} - Flask Super Example</h1>
{% 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) %}
  <li class="active"><a href="{{ url_for(endpoint) }}">{{name}}</a></li>
{% else %}
  <li><a href="{{ url_for(endpoint) }}">{{name}}</a></li>
{% endif %}
{% endmacro %}

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

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

<ul class="nav navbar-nav">
  {{ nav_link('home', 'Home') }}
  {{ nav_link('about', 'About') }}
  {{ nav_link('contact', 'Contact Us') }}
</ul>

此外,请确保在模板顶部添加导入:{% 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)这样,我们在子模板中插入如下代码:

<h4>Current date/time: {{ current_time | datetimefilter }}</h4>

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

current_time = datetime.datetime.now()

5)效果如下:

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分钟送到会用(只能送你到这了)

到此这篇关于python中的flask框架Jinja 模板入门的文章就介绍到这了,更多相关python flask Jinja 模板内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

python中的flask框架Jinja 模板入门教程的更多相关文章

  1. XCode 3.2 Ruby和Python模板

    在xcode3.2下,我的ObjectiveCPython/Ruby项目仍然可以打开更新和编译,但是你无法创建新项目.鉴于xcode3.2中缺少ruby和python的所有痕迹(即创建项目并添加新的ruby/python文件),是否有一种简单的方法可以再次安装模板?我发现了一些关于将它们复制到某个文件夹的信息,但我似乎无法让它工作,我怀疑文件夹的位置已经改变为3.2.解决方法3.2中的应用程序模板

  2. Swift基本使用-函数和闭包(三)

    声明函数和其他脚本语言有相似的地方,比较明显的地方是声明函数的关键字swift也出现了Python中的组元,可以通过一个组元返回多个值。传递可变参数,函数以数组的形式获取参数swift中函数可以嵌套,被嵌套的函数可以访问外部函数的变量。可以通过函数的潜逃来重构过长或者太复杂的函数。

  3. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  4. Swift、Go、Julia与R能否挑战 Python 的王者地位

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 红薯因 Swift 重写开源中国失败,貌似欲改用 Python

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  6. 你没看错:Swift可以直接调用Python函数库

    上周Perfect又推出了新一轮服务器端Swift增强函数库:Perfect-Python。对,你没看错,在服务器端Swift其实可以轻松从其他语种的函数库中直接拿来调用,不需要修改任何内容。以如下python脚本为例:Perfect-Python可以用下列方法封装并调用以上函数,您所需要注意的仅仅是其函数名称以及参数。

  7. Swift中的列表解析

    在Swift中完成这个的最简单的方法是什么?我在寻找类似的东西:从Swift2.x开始,有一些与你的Python样式列表解析相当的东西。(在这个意义上,它更像是Python的xrange。如果你想保持集合懒惰一路通过,只是这样说:与Python中的列表解析语法不同,Swift中的这些操作遵循与其他操作相同的语法。

  8. swift抛出终端的python错误

    每当我尝试启动与python相关的swift时,我都会收到错误.我该如何解决?

  9. 在Android上用Java嵌入Python

    解决方法看看this,它适用于J2SE,你可以尝试在Android上运行.

  10. 使用Retrofit在Android中重新创建flask api调用

    我在服务器上有一个烧瓶app和api,它使用从终端发送的以下url我试图在Android上使用改造来重新创建它.我使用的是1.7版,因为这适用于此处未显示的一些遗留代码.这是应用程序类的相关部分和api类我现在只得到一般性错误,例如这是我的第一个烧瓶应用程序,我不完全确定如何调试所以任何帮助在这里也是赞赏.我也没有访问服务器日志更新为了尝试追踪问题,我编辑了服务器上的代码.如果我只是在api中返回

随机推荐

  1. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  2. python数学建模之三大模型与十大常用算法详情

    这篇文章主要介绍了python数学建模之三大模型与十大常用算法详情,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感想取得小伙伴可以参考一下

  3. Python爬取奶茶店数据分析哪家最好喝以及性价比

    这篇文章主要介绍了用Python告诉你奶茶哪家最好喝性价比最高,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

  4. 使用pyinstaller打包.exe文件的详细教程

    PyInstaller是一个跨平台的Python应用打包工具,能够把 Python 脚本及其所在的 Python 解释器打包成可执行文件,下面这篇文章主要给大家介绍了关于使用pyinstaller打包.exe文件的相关资料,需要的朋友可以参考下

  5. 基于Python实现射击小游戏的制作

    这篇文章主要介绍了如何利用Python制作一个自己专属的第一人称射击小游戏,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起动手试一试

  6. Python list append方法之给列表追加元素

    这篇文章主要介绍了Python list append方法如何给列表追加元素,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  7. Pytest+Request+Allure+Jenkins实现接口自动化

    这篇文章介绍了Pytest+Request+Allure+Jenkins实现接口自动化的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. 利用python实现简单的情感分析实例教程

    商品评论挖掘、电影推荐、股市预测……情感分析大有用武之地,下面这篇文章主要给大家介绍了关于利用python实现简单的情感分析的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

  9. 利用Python上传日志并监控告警的方法详解

    这篇文章将详细为大家介绍如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务,感兴趣的小伙伴可以了解一下

  10. Pycharm中运行程序在Python console中执行,不是直接Run问题

    这篇文章主要介绍了Pycharm中运行程序在Python console中执行,不是直接Run问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

返回
顶部