Jinja2 模板的学习

默认情况下,Flask 在程序文件夹中的 templates 子文件夹中寻找模板。在下一个 hello.py 版本中,要把前面定义的模板保存在 templates 文件夹中,并分别命名为 index.html 和 user.html。

index.thm的代码如下,不传参数


    
        欢迎来到王者荣耀 
    
    
        

你是不是要成为一个高手

user.html中传递一个参数


    
        欢迎来到王者荣耀 
    
    
        

你是不是要成为一个高手,你的名字是{{name}}

在hello.py中,

from flask import render_template
@app.route('/')
def index():
    return render_template('index.html')
@app.route('/user/') #尖括号中的动态名字
def user(name):
    return render_template('user.html',name=name)

1、变量

在模板中使用的 {{ name }} 结构表示一个变量,它是一种特殊的占位符,告诉模
板引擎这个位置的值从渲染模板时使用的数据中获取。
Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。在模板 中使用变量的一些示例如下:

     

A value from a dictionary: {{ mydict['key'] }}.

A value from a list: {{ mylist[3] }}.

A value from a list, with a variable index: {{ mylist[myintvar] }}.

A value from an object's method: {{ myobj.somemethod() }}.

可以使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。例如,下述 模板以首字母大写形式显示变量 name 的值:

Hello, {{ name|capitalize }}

下面是常用的过滤器

Jinja2 模板的学习_第1张图片
8568F68D-6315-4E2D-88A3-205D6C011941.png

更多的fliter官方文档

2、Jinja2的控制结构

if - else 的写法

    {% if name %}
        Hello,{{name}}
    {% else %}
        Hello ,你没名字一看就是菜啊!!!
    {% endif %}

for 循环

    {% for title in ["黄金4","黄金3","黄金2"] %}
        
  • {{title}}
  • {% endfor %}

    Jinja2 还支持宏。宏类似于 Python 代码中的函数。例如:

    {% macro render_comment(comment) %} 
           
  • {{ comment }}
  • {% endmacro %}
      {% for comment in comments %} {{ render_comment(comment) }} {% endfor %}

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

    {% import 'macros.html' as macros %}
     
      {% for comment in comments %} {{ macros.render_comment(comment) }} {% endfor %}

    需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免 重复:

    {% include 'common.html' %}
    

    另一种重复使用代码的强大方式是模板继承,它类似于 Python 代码中的类继承。首先,创
    建一个名为 base.html 的基模板:

    
        
            {% block head %}
            {% block title %}{% endblock %} - MyApplication
            {% endblock %}
        
        
            {%block body %}
            

    我是来自基类

    {%endblock %}

    新建一个son.html 继承base.html

    {% extends "base.html" %}
    {% block title %} INDEX {% endblock %}
    {% block head %}
        {{super()}}
    {% endblock %}
    {% block body %}
    {{super()}}
    

    我也是醉了,这是啥基础自基础模板

    {% endblock %}

    extends 指令声明这个模板衍生自 base.html。在 extends 指令之后,基模板中的 3 个块被 重新定义,模板引擎会将其插入适当的位置。注意新定义的 head 块,在基模板中其内容不 是空的,所以使用 super() 获取原来的内容。

    3、自定义错误页面的方式

    自定义错误页面
         @app.errorhandler(404)
         def page_not_found(e):
             return render_template('404.html'), 404
         @app.errorhandler(500)
         def internal_server_error(e):
             return render_template('500.html'), 500
    

    4、链接

    任何具有多个路由的程序都需要可以连接不同页面的链接,例如导航条。
    在模板中直接编写简单路由的 URL 链接不难,但对于包含可变部分的动态路由,在模板 中构建正确的 URL 就很困难。而且,直接编写 URL 会对代码中定义的路由产生不必要的 依赖关系。如果重新定义路由,模板中的链接可能会失效。
    为了避免这些问题,Flask 提供了 url_for() 辅助函数,它可以使用程序 URL 映射中保存 的信息生成 URL。
    url_for() 函数最简单的用法是以视图函数名(或者 app.add_url_route() 定义路由时使用 的端点名)作为参数,返回对应的 URL。例如,在当前版本的 hello.py程序中调用 url_ for('index')得到的结果是/。调用url_for('index', _external=True)返回的则是绝对地 址,在这个示例中是 http://localhost:5000/。
    生成连接程序内不同路由的链接时,使用相对地址就足够了。如果要生成在 浏览器之外使用的链接,则必须使用绝对地址,例如在电子邮件中发送的 链接。
    使用 url_for() 生成动态地址时,将动态部分作为关键字参数传入。例如,url_for ('user', name='john', _external=True) 的返回结果是 http://localhost:5000/user/john。
    传入 url_for() 的关键字参数不仅限于动态路由中的参数。函数能将任何额外参数添加到 查询字符串中。例如,url_for('index', page=2) 的返回结果是 /?page=2。

    5、静态文件

    Web 程序不是仅由 Python 代码和模板组成。大多数程序还会使用静态文件,例如 HTML
    代码中引用的图片、JavaScript 源码文件和 CSS。
    例如,调用 url_for('static', filename='css/styles.css', _external=True) 得 到 的 结 果 是 http:// localhost:5000/static/css/styles.css。
    默认设置下,Flask 在程序根目录中名为 static 的子目录中寻找静态文件。如果需要,可在 static 文件夹中使用子文件夹存放文件。服务器收到前面那个 URL 后,会生成一个响应, 包含文件系统中 static/css/styles.css 文件的内容。

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

    有一个使用 JavaScript 开发的优秀客户端开源代码库,名为 moment.js(http://momentjs. com/),它可以在浏览器中渲染日期和时间。Flask-Moment 是一个 Flask 程序扩展,能把 moment.js 集成到 Jinja2 模板中。Flask-Moment 可以使用 pip 安装:

     pip3 install flask-moment
    

    这个扩展的初始化方法如示例 3-11 所示。 示例 3-11 hello.py:初始化 Flask-Moment

    from flask.ext.moment import Moment moment = Moment(app)
    
    

    7、使用Flask-Bootstrap集成Twitter Bootstrap

    安装

     pip3 install flask-bootstrap
    

    初始化 Flask-Bootstrap

    from flask_bootstrap import Bootstrap
    bootstrap = Bootstrap(app)
    

    新建一个home.html模板,继承bootstrap的base.html模板

    {% extends "bootstrap/base.html" %}
    {% block title %}Flasky{% endblock %}
    {% block navbar %}
    
    {% endblock %}
    {% block content %} 
    {% endblock %}

    Flask-Bootstrap 的 base.html 模板还定义了很多其他块,都可在衍生模板中使用。表 3-2 列

    Jinja2 模板的学习_第2张图片
    ![Uploading 18C6212F-F78C-4AA2-8281-9FAB2C5FC341_474250.png . . .]
    Jinja2 模板的学习_第3张图片
    18C6212F-F78C-4AA2-8281-9FAB2C5FC341.png

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

    {% block scripts %}
    {{ super() }}
     
    {% endblock %}
    

    7、web表单

    尽管 Flask 的请求对象提供的信息足够用于处理 Web 表单,但有些任务很单调,而且要重 复操作。比如,生成表单的 HTML 代码和验证提交的表单数据。
    Flask-WTF(http://pythonhosted.org/Flask-WTF/)扩展可以把处理 Web 表单的过程变成一 种愉悦的体验。这个扩展对独立的 WTForms(http://wtforms.simplecodes.com)包进行了包 装,方便集成到 Flask 程序中。
    Flask-WTF 及其依赖可使用 pip 安装:

    pip3 install flask-wtf
    

    默认情况下,Flask-WTF能保护所有表单免受跨站请求伪造(Cross-Site Request Forgery,
    CSRF)的攻击。恶意网站把请求发送到被攻击者已登录的其他网站时就会引发 CSRF 攻击。 为了实现 CSRF 保护,Flask-WTF 需要程序设置一个密钥。Flask-WTF 使用这个密钥生成
    加密令牌,再用令牌验证请求中表单数据的真伪。设置密钥的方法设置 Flask-WTF

    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'hard to guess string'
       33
    

    app.config 字典可用来存储框架、扩展和程序本身的配置变量。使用标准的字典句法就能 把配置值添加到 app.config 对象中。这个对象还提供了一些方法,可以从文件或环境中导 入配置值。
    SECRET_KEY 配置变量是通用密钥,可在 Flask 和多个第三方扩展中使用。如其名所示,加 密的强度取决于变量值的机密程度。不同的程序要使用不同的密钥,而且要保证其他人不 知道你所用的字符串。

    表单类:
    使用 Flask-WTF 时,每个 Web 表单都由一个继承自 Form 的类表示。这个类定义表单中的 一组字段,每个字段都用对象表示。字段对象可附属一个或多个验证函数。验证函数用来 验证用户提交的输入值是否符合要求。
    下面是一个简单的 Web 表单,包含一个文本字段和一个提交按钮。

    from flask_wtf import Form
    from wtforms import StringField, SubmitField 
    from wtforms.validators import Required
    class NameForm(Form):
        name = StringField('What is your name?', validators=[Required()]) 
        submit = SubmitField('Submit')
    

    这个表单中的字段都定义为类变量,类变量的值是相应字段类型的对象。在这个示例中, NameForm 表单中有一个名为 name 的文本字段和一个名为 submit 的提交按钮。StringField 类表示属性为 type="text" 的 元素。SubmitField 类表示属性为 type="submit" 的 元素。字段构造函数的第一个参数是把表单渲染成 HTML 时使用的标号。
    StringField 构造函数中的可选参数 validators 指定一个由验证函数组成的列表,在接受 用户提交的数据之前验证数据。验证函数 Required() 确保提交的字段不为空。

    WTForms 支持的 HTML 标准字段如下图

    Jinja2 模板的学习_第4张图片
    9278B3CA-AF23-4D0D-82F1-069F17A27188.png

    WTForms 内建的验证函数

    Jinja2 模板的学习_第5张图片
    3A0C9B81-7C18-404B-AC94-6E71EDE4FEE5.png

    把表单类渲染为HTML
    例通过参数 form 传入模板,在模板中可以生成一个简单的表单,如下所示:

         
    {{ form.hidden_tag() }} {{ form.name.label }} {{ form.name() }} {{ form.submit() }}

    即便能指定 HTML 属性,但按照这种方式渲染表单的工作量还是很大,所以在条件允许的 情况下最好能使用 Bootstrap 中的表单样式。Flask-Bootstrap 提供了一个非常高端的辅助函 数,可以使用 Bootstrap 中预先定义好的表单样式渲染整个 Flask-WTF 表单,而这些操作 只需一次调用即可完成。使用 Flask-Bootstrap,上述表单可使用下面的方式渲染:

    {% import "bootstrap/wtf.html" as wtf %}
     {{ wtf.quick_form(form) }}
    

    Flash消息
    请求完成后,有时需要让用户知道状态发生了变化。这里可以使用确认消息、警告或者错 误提醒。一个典型例子是,用户提交了有一项错误的登录表单后,服务器发回的响应重新 渲染了登录表单,并在表单上面显示一个消息,提示用户用户名或密码错误。
    这种功能是 Flask 的核心特性。

    @app.route('/',methods = ['GET','POST'])
    def index():
        name = None
        form = NameForm()
        if form.validate_on_submit():
            
            old_name = session.get('name')
            new_name = form.name.data
            session['name'] = new_name
            if old_name is not None and old_name != new_name:
                flash('你似乎改变了你的名字')
            return redirect(url_for('index'))
            
        return render_template('testForm.html', form=form, name=session.get('name'))
    

    在这个示例中,每次提交的名字都会和存储在用户会话中的名字进行比较,而会话中存储 的名字是前一次在这个表单中提交的数据。如果两个名字不一样,就会调用 flash() 函数, 在发给客户端的下一个响应中显示一个消息。

    获取get_flashed_messages()来获取消息
    在html中显示消息

    {% for message in get_flashed_messages() %}
            
    {{message}}
    {% endfor %}

    你可能感兴趣的:(Jinja2 模板的学习)