Flask四之模板

四、模板

FMTV
F:form表单
M:Model模型(数据库)
T:Template模板
V:view视图(路由)

1、渲染模板

模板是一个包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体值
只在请求的上下文中才能知道。 使用真实值替换变量,再返回最终得到的响应字符
串,这一过程称为渲染。可以使用 render_template() 方法来渲染模板。你需要做
的一切就是将模板名和你想作为关键字的参数传入模板的变量。
Flask 会在 templates 文件夹里寻找模板。所以,如果你的应用是个模块,这个文
件夹应该与模块同级;如果它是一个包,那么这个文件夹作为包的子目录:
模板:
/application.py
/templates
    /hello.html

包:

/application
    /__init__.py
    /templates
        /hello.html

【hello.html】

<h1>Hello World!</h1>


from flask import render_template
@app.route('/hellotemplate/')
def hellotemplate():
    return render_template('hello.html')

模板引擎
Flask使用了一个名为 Jinja2 的强大模板引擎

  • {% … %} Jinja语句,例如判断、循环语句

  • {{ … }} 变量,会显示在浏览器中

  • {# … #} 注释,不会输出到浏览器中

2、变量规则

在模板中使用的 {{ name }} 结构表示一个变量,它是一种特殊的占位符,告诉
模板引擎这个位置的值从渲染模板时使用的数据中获取。
【helloname.html】

<h1>Hello, {{ name }}!</h1>

@app.route('/hellotemplate/<name>')
def helloname(name):
    return render_template('helloname.html',name = name)

可以使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。

3、控制结构

1、条件控制语句
【if.html】

{% if name %}
hello, {{name}}
{% else %}
hello, world!
{% endif %}

2、 for 循环
【for.html】

<ol>
    {% for a in range(10) %}
    <li>a</li>
    {% endfor %}
</ol>

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

3、Jinja2 还支持宏(macro) 。宏类似于 Python 代码中的函数(def)。
【macro.html】

{% macro myprint(A) %}
this is {{ A }}
{% endmacro %}

{{ myprint(A) }}


@app.route('/macro/<a>')
def macrotamplate(a):
    return render_template('macro.html',A = a)

为了重复使用宏,我们可以将其保存在单独的文件中,然后在需要使用的模板中导入:
【macro2.html】

{% from 'macro.html' import myprint %}
{{ myprint(A) }}

@app.route('/macro2/<a>')
def macro2template(a):
    return render_template('macro2.html',A = a)

4、包含(include)
【include.html】

{% include 'macro.html' %}


@app.route('/include/<a>')
def includetemplate(a):
    return render_template('include.html',A = a)

【注意】
包含进来的文件里的所有变量也包含进来了,需要在视图函数中指定

4、模板继承

首先,创建一个名为 base.html 的基模板:
【base.html】

<html>
<head>
    {% block head %}
    <title>
        {% block title %}
        {% endblock %}
        - My Application
    </title>
    {% endblock %}
</head>

<body>
{% block body %}
{% endblock %}
</body>

</html>

block 标签定义的元素可在衍生模板中修改。下面这个示例是基模板的衍生模板:
【extend.html】

% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<h1>super</h1>
{% endblock %}
{% block body %}
<h1>Hello, World!</h1>
{% endblock %}
extends 指令声明这个模板衍生自 base.html。在 extends 指令之后,基模板中的
3个块被重新定义,模板引擎会将其插入适当的位置。如果想添加内容到在父模板
内已经定义的块,又不想失去父模板里的内容,可以使用super函数

5、使用Flask-Bootstrap

Flask-Bootstrap 使用 pip安装:

(venv) $ pip install flask-bootstrap

Flask 扩展一般都在创建程序实例后就初始化。
初始化 Flask-Bootstrap 之后,就可以在程序中使用一个包含所有 Bootstrap 文件
的基模板。
【boootstrap.html】

{% extends "bootstrap/base.html" %}

{% block title %}Flasky{% endblock %}

{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle"
                    data-toggle="collapse" data-target=".navbar-collapse">
                <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="/">Flasky</a>
        </div>
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="/">Home</a></li>
            </ul>
        </div>
    </div>
</div>
{% endblock %}

{% block content %}
<div class="container">
    <div class="page-header">
        <h1>Hello, {{ name }}!</h1>
    </div>
</div>
{% endblock %}
Jinja2 中的 extends 指令从 Flask-Bootstrap 中导入 bootstrap/base.html,从而
实现模板继承。

Flask-Bootstrap 中的基模板提供了一个网页框架,引入了 Bootstrap 中的所有 CSS 
和JavaScript 文件。基模板中定义了可在衍生模板中重定义的块。 block 和 endblock 
指令定义的块中的内容可添加到基模板中。
上面这个 boootstrap.html 模板定义了 3 个块,分别名为 title、 navbar 和 content。
这些块都是基模板提供的, 可在衍生模板中重新定义。 title 块的作用很明显,其中
的内容会出现在渲染后的 HTML 文档头部,放在 <title> 标签中。 navbar 和 content 
这两个块分别表示页面中的导航条和主体内容。在这个模板中, navbar 块使用 Bootstrap 
组件定义了一个简单的导航条。content 块中有个<div> 容器,其中包含一个页面头部。
之前版本的模板中的欢迎信息,现在就放在这个页面头部。
from flask_bootstrap import Bootstrap
bootstrap = Bootstrap(app)
@app.route('/bootstrap/<name>')
def bootstraptemplate(name):
    return render_template('boootstrap.html',name = name)

【注意】
很多块都是 Flask-Bootstrap 自用的,如果直接重定义可能会导致一些问题。例如,
Bootstrap 所需的文件在 styles 和 scripts 块中声明。如果程序需要向已经有内
容的块中添加新内容,必须使用Jinja2 提供的 super() 函数。例如,如果要在衍生
模板中添加新的 JavaScript 文件,需要这么定义 scripts 块:

{% block scripts %}
{{ super() }}
<script type="text/javascript" src="my-script.js"></script>
{% endblock %}

6、自定义错误页面

【templates/404.html】

<h1> Page is not Found </h1>
@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

【templates/base.html: 包含导航条的程序基模板】

{% extends "bootstrap/base.html" %}

{% block title %}Flasky{% endblock %}

{% block head %}
{{ super() }}
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x -icon">
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x -icon">
{% endblock %}

{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <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="/">Flasky</a>
        </div>
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="/">Home</a></li>
            </ul>
        </div>
    </div>
</div>
{% endblock %}

{% block content %}
<div class="container">
{% block page_content %}{% endblock %}
</div>
{% endblock %}

{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}

这个模板的 content 块中只有一个 <div> 容器,其中包含了一个名为
page_content 的新的空块,块中的内容由衍生模板定义。

【templates/404.html:使用模板继承机制自定义 404 错误页面】

{% extends "base.html" %}
{% block title %}Flasky - Page Not Found{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Not Found</h1>
</div>
{% endblock %}

templates/boootstrap.html 现在可以通过继承这个基模板来简化内容:
【 templates/boootstrap.html: 使用模板继承机制简化页面模板】

{% extends "base.html" %}
{% block title %}Flasky{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Hello, {{ name }}!</h1>
</div>
{% endblock %}

7、静态文件

默认设置下, Flask 在程序根目录中名为 static 的子目录中寻找静态文件。
如果需要,可在static 文件夹中使用子文件夹存放文件。给静态文件生成
URL ,使用特殊的 ‘static’ 端点名:
【westeros.html】

<img src = "{{url_for('static',filename = 'westeros.jpg')}}">
@app.route('/westeros/')
def westeros():
    return render_template('westeros.html')

这个文件应该存储在文件系统上的 static/westeros.jpg 。

8、使用Flask-Moment本地化日期和时间

lask-Moment 是一个 Flask 程序扩展,能把moment.js 集成到 Jinja2 模
板中。 Flask-Moment 可以使用 pip 安装:

(venv) $ pip install flask-moment

这个扩展的初始化方法和Bootstrap一样,以程序实例app为参数:

from flask_moment import Moment
moment = Moment(app)

除了 moment.js, Flask-Moment 还依赖 jquery.js。要在 HTML 文档的某个
地方引入这两个库,可以直接引入,这样可以选择使用哪个版本,也可使用扩
展提供的辅助函数,从内容分发网络(Content Delivery Network, CDN)中
引入通过测试的版本。 Bootstrap 已经引入了 jquery.js, 因此只需引入
moment.js即可。
【base.html中增加了】

{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}

【moment.html】

{% extends "base.html" %}
{% block page_content %}
<div class="page-header">
<h1>Hello World!</h1>
</div>
<p>The local date and time is {{moment(current_time).format('LLL')}}.</p>
<p>That was {{moment(current_time).fromNow(refresh = true)}}.</p>
{% endblock %}

把变量current_time 传入模板进行渲染

from datetime import datetime
@app.route('/moment/')
def momenttemplate():
return render_template('moment.html',current_time = datetime.utcnow())
    原文作者:netScorpion
    原文地址: https://segmentfault.com/a/1190000010954873
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞