Flask-模板引擎

flask-script

  • 说明:flask终端启动的参数解析器,只需要通过启动传递不同的参数即可完成不同方式的启动
  • 安装:pip install flask-script
  • 使用:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from flask import Flask
    from flask_script import Manager


    app = Flask(__name__)
    # 创建对象
    manager = Manager(app)

    @app.route('/')
    def index():
    return 'Hello Flask'

    if __name__=="__main__":
    # app.run(debug=True)
    manager.run()

    启动:python manager.py runserver

  • 启动参数
    1
    2
    3
    4
    5
    6
    -? 或 --help     # 查看使用帮助
    -h 或 --host # 指定主机
    -p 或 --port # 指定端口
    --threaded # 开启多线程
    -d # 开启调试模式
    -r # 重新加载

    启动示例:python manager.py runserver -d -r

蓝本(blueprint)

  • 说明:当项目越来越复杂时,所有的视图函数都放在一个文件中,很明显是不合适的;如果能够根据功能需求划分到不同的文件中就好了,幸好有蓝本的存在,专门用于解决此问题。

  • 使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from flask import Blueprint

    # 创建蓝本对象
    user = Blueprint('user', __name__, url_prefix='/user')


    # 添加路由
    @user.route('/login/')
    def login():
    return '欢迎登录'
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    from flask import Flask
    from flask_script import Manager

    app = Flask(__name__)
    # 创建对象
    manager = Manager(app)


    @app.route('/')
    def index():
    return 'Hello Flask'


    # 注册蓝本,可以指定路由前缀,创建时也可以指定,但注册时优先级高
    from user import user

    app.register_blueprint(user, url_prefix='/u')

    if __name__ == "__main__":
    # app.run(debug=True)
    manager.run()

模板引擎

  • 说明:
    • 模板文件是按照特定语法规则书写的专门负责显示特定效果的文件;
    • 模板引擎就是负责特定语法规则的解析和替换的工具。
  • Jinja2:
    • flask中使用的是Jinja2的模板引擎,它是flask核心开发者人员开发的。

Jinja2使用流程

  • 创建工程,准备目录

    1
    2
    3
    project/			# 工程目录
    manage.py # 启动控制文件
    templates/ # 模板文件目录
  • 准备模板文件

    • 在templates下创建一个hello.html模板文件,内容如下

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <title>模板引擎测试</title>
      </head>
      <body>
      <h1>Hello Flask</h1>
      </body>
      </html>
  • 模板渲染:需要使用专门的渲染函数

    1. 渲染模板文件:render_template
    2. 渲染模板字符串:render_template_string
  • 开启自动加载模板文件

    1
    2
    # 模板文件修改后自动加载
    app.config['TEMPLATES_AUTO_RELOAD'] = True
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    from flask import Flask, render_template, render_template_string
    from flask_script import Manager

    app = Flask(__name__)
    manager = Manager(app)

    # 模板文件修改后自动加载
    app.config['TEMPLATES_AUTO_RELOAD'] = True


    @app.route('/')
    def index():
    # return '<h1>Flask-template</h1>'
    # 渲染模板文件
    # return render_template('hello.html')
    # 渲染模板字符串
    return render_template_string('<h1>渲染模板字符串</h1>')


    if __name__ == '__main__':
    manager.run()

使用变量

  • 模板文件中:

    1
    {{ 变量名 }}
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>变量</title>
    </head>
    <body>
    <h1>Hello {{ name }}!</h1>
    <h1>Hello {{ g.name }}!</h1>
    </body>
    </html>
  • 渲染时:render_template('模板文件名', 变量名=变量值)

    1
    2
    3
    4
    5
    @app.route('/var/')
    def var():
    # 可以在模板中直接使用,渲染时不需要分配
    g.name = 'curry'
    return render_template('var.html', name='ergouzi')
  • 示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    from flask import Flask, render_template, render_template_string, g
    from flask_script import Manager

    app = Flask(__name__)
    manager = Manager(app)

    # 模板文件修改后自动加载
    app.config['TEMPLATES_AUTO_RELOAD'] = True


    @app.route('/')
    def index():
    # return '<h1>Flask-template</h1>'
    # 渲染模板文件
    # return render_template('hello.html')
    # 渲染模板字符串
    return render_template_string('<h1>渲染模板字符串</h1>')


    @app.route('/var/')
    def var():
    # 可以在模板中直接使用,渲染时不需要分配
    g.name = 'curry'
    return render_template('var.html', name='ergou')


    if __name__ == '__main__':
    manager.run()

使用函数

  • 模板文件中渲染变量时:

    1
    {{ 变量名 | 函数名 }}
  • 示例:

    1
    <h1>Hello {{ name | upper }}!</h1>
  • 常用函数:

    函数 说明
    upper 全部大写
    lower 全部小写
    title 每个单词首字母大写
    capitalize 首字母大写
    trim 去掉两遍空白
    striptags 过滤HTML标签
    safe 渲染时不转义,默认转义

    safe不要乱用,只能用在足够信任的变量渲染中

流程控制

  • 分支结构(if-else)

    1
    2
    3
    4
    5
    {% if name %}
    <h1>Hello {{ name }}!</h1>
    {% else %}
    <h1>Hello World!</h1>
    {% endif %}
  • 循环结构(for-in)

    1
    2
    3
    4
    5
    <ol>
    {% for i in range(1, 11) %}
    <li>{{ i }}</li>
    {% endfor %}
    </ol>
  • 说明:

    1
    将控制语句写在{%  %}中
  • 注释:

    1
    写在{#  #}中

文件包含

  • 说明:就是原封不动的将另一个文件中的内容加载过来,避免了重新书写工作。
  • 使用:
    1
    2
    # {% include '被包含模板文件名' %}
    {% include 'include2.html' %}

宏的使用

  • 需要先定义在使用
  • 格式:
    • 定义宏
      1
      2
      3
      {% macro 宏名(参数) %}
      宏的内容
      {% endmacro %}
    • 调用宏
      1
      {{ 宏名(参数) }}
  • 示例:
    1
    2
    3
    4
    5
    6
    7
    {# 定义宏 #}
    {% macro show_name(name) %}
    <h1>Hello {{ name }}!</h1>
    {% endmacro %}

    {# 调用宏 #}
    {{ show_name(name) }}
  • 导入宏:
    1
    2
    3
    4
    5
    6
    7
    {% from '文件名' import 宏名 %}

    {# 导入宏 #}
    {% from 'macro.html' import show_name %}

    {# 调用宏 #}
    {{ show_name(name) }}
  • 说明:宏的使用采用与python中函数一样的方式进行定义和调用。

模板继承

  • 基础模板,用来被继承
  • 子模板,继承自基础模板
    1
    {% extends '基础模板' %}
  • 块标识:
    1
    {% block 块名 %}{% endblock %}
  • 块重写:在子模板中,可以通过同名block的书写对继承的内容进行重写或删除
  • 保留基础模板内容:
    1
    {{ super() }}
  • 说明:在模板继承使用过程中,若重写了一个block后发现完全错了,很可能是没有使用
    1
    {{ super() }}
  • 示例:
    • 基础模板
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <title>{% block title %}父级模板标题{% endblock %}</title>
      </head>
      <body>
      {% block body %}
      默认内容
      {% endblock %}
      </body>
      </html>
    • 子模板
      1
      2
      3
      4
      5
      6
      7
      8
      9
      {# 继承自父级模板 #}
      {% extends 'parent.html' %}

      {% block title %}欢迎登录{% endblock %}
      {% block body %}
      {# 保留继承的内容 #}
      {{ super() }}
      欢迎你的到来。。。
      {% endblock %}

flask-bootstrap

  • 安装:pip install flask-bootstrap
  • 初始化:
    1
    2
    3
    4
    5
    from flask_bootstrap import Bootstrap
    bootstrap = Bootstrap(app)
    # 若创建时app不存在,可以先创建再初始化
    # bootstrap = Bootstrap()
    # bootstrap.init_app(app)
  • 模板继承
    1
    2
    {# 继承自bootstrap的基础模板 #}
    {% extends 'bootstrap/base.html' %}
  • 说明:通过重写基础模板定义的block即可完成特定效果的展示
  • bootstrap基础模板中提供的block
    block 说明
    doc 整个HTML文档
    html 整个HTML标签
    head head标签
    title title标签
    styles 引入CSS样式
    metas 一组meta标签
    body body标签
    navbar 用户自定义的导航条
    content 用户自定义内容
    script 引入JS文件

    使用bootstrap时,若重写了一个block,原来的显示效果消失,八成是因为忘记了super。

定制项目基础模板

  • 说明:在很多网站中,绝大多数页面长得几乎一模一样,只有个别区域的差别;若每个页面都单独定制势必会出现大量的重复代码,为了解决此类问题,最好定制一个基础,将大致的内容全部写好,并且全部起好名字,然后让其他页面继承自该基础模板,简单修改即可达到想要的效果。
  • 步骤:
    • 从bootstrap官网复制一个顺眼的导航条
    • 显示反色导航条:navbar-inverse
    • 修改容器布局:container-fluid => container
    • 定制圆角:style="border-radius: 0"
    • 根据需要定制导航条上的内容
    • 修改折叠内容的定位方式 id => calss
  • 基础模板示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    {% extends 'bootstrap/base.html' %}

    {% block title %}默认标题{% endblock %}

    {% block navbar %}
    <nav class="navbar navbar-inverse" style="border-radius: 0">
    <div class="container">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
    data-target=".navbar-collapse" aria-expanded="false">
    <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="#">首页</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse">
    <ul class="nav navbar-nav">
    <li><a href="#">版块一</a></li>
    <li><a href="#">版块二</a></li>
    <li><a href="#">板块三</a></li>
    </ul>
    <ul class="nav navbar-nav navbar-right">
    <li><a href="#">登录</a></li>
    <li><a href="#">注册</a></li>
    </ul>
    </div><!-- /.navbar-collapse -->
    </div><!-- /.container -->
    </nav>
    {% endblock %}

    {% block content %}
    <div class="container">
    {% block page_content %}
    默认内容
    {% endblock %}
    </div>
    {% endblock %}

练习

1
2
1.定制登录页面、注册页面、404页面
2.试着完成静态文件的加载