模板

在Flask Web开发中,一般是提供一个HTML模板文件,然后将数据传递到模板中,在渲染HTML模板文件后会得到最终的HTML响应文件。
  • 原先的视图函数返回简单的字符串,我现在要将其扩展为包含完整HTML页面元素的字符串
  1. from app import app
  2. @app.route('/')
  3. @app.route('/index')
  4. def index():
  5. user = {'username': 'Miguel'}
  6. return '''
  7. <html>
  8. <head>
  9. <title>Home Page - Microblog</title>
  10. </head>
  11. <body>
  12. <h1>Hello, ''' + user['username'] + '''!</h1>
  13. </body>
  14. </html>'''
  • 模板有助于实现页面展现和业务逻辑之间的分离。 在Flask中,模板被编写为单独的文件,存储在应用程序包内的templates文件夹中.
  1. (venv) $ mkdir app/templates
  • 创建模板,这个文件写在app/templates/index.html中
  1. <html>
  2. <head>
  3. <title>{{ title }} - Microblog</title>
  4. </head>
  5. <body>
  6. <h1>Hello, {{ user.username }}!</h1>
  7. </body>
  8. </html>
  • {{ … }}包含的内容是动态的,网页渲染转移到HTML模板之后,视图函数就能被简化:
  1. from flask import render_template
  2. from app import app
  3. @app.route('/')
  4. @app.route('/index')
  5. def index():
  6. user = {'username': 'Miguel'}
  7. return render_template('index.html', title='Home', user=user)
  • 渲染模板,使用render_template() 函数,该函数需要传入模板文件名和模板参数的变量列表,并返回模板中所有占位符都用实际变量值替换后的字符串结果。
  • render_template()函数调用Flask框架原生依赖的Jinja2模板引擎。

条件分支
  • 模板支持条件语句,在渲染过程中使用实际值替换占位符。
  1. <html>
  2. <head>
  3. {% if title %}
  4. <title>{{ title }} - Microblog</title>
  5. {% else %}
  6. <title>Welcome to Microblog!</title>
  7. {% endif %}
  8. </head>
  9. <body>
  10. <h1>Hello, {{ user.username }}!</h1>
  11. </body>
  12. </html>

循环
  • 登录后的用户可能想要在主页上查看其他用户的最新动态,针对这个需求:
  1. from flask import render_template
  2. from app import app
  3. @app.route('/')
  4. @app.route('/index')
  5. def index():
  6. user = {'username': 'Miguel'}
  7. posts = [
  8. {
  9. 'author': {'username': 'John'},
  10. 'body': 'Beautiful day in Portland!'
  11. },
  12. {
  13. 'author': {'username': 'Susan'},
  14. 'body': 'The Avengers movie was so cool!'
  15. }
  16. ]
  17. return render_template('index.html', title='Home', user=user, posts=posts)
  • 在模板方面,我必须解决一个新问题。 用户动态列表拥有的元素数量由视图函数决定。 那么模板不能对有多少个用户动态进行任何假设,因此需要准备好以通用方式渲染任意数量的用户动态。
  1. <html>
  2. <head>
  3. {% if title %}
  4. <title>{{ title }} - Microblog</title>
  5. {% else %}
  6. <title>Welcome to Microblog</title>
  7. {% endif %}
  8. </head>
  9. <body>
  10. <h1>Hi, {{ user.username }}!</h1>
  11. {% for post in posts %}
  12. <div><p>{{ post.author.username }} says: <b>{{ post.body }}</b></p></div>
  13. {% endfor %}
  14. </body>
  15. </html>

模板的继承与复用
  • 定义一个名为base.html的基本模板,app/templates/base.html中编写代码如下:
  1. <html>
  2. <head>
  3. {% if title %}
  4. <title>{{ title }} - Microblog</title>
  5. {% else %}
  6. <title>Welcome to Microblog</title>
  7. {% endif %}
  8. </head>
  9. <body>
  10. <div>Microblog: <a href="/index">Home</a></div>
  11. <hr>
  12. {% block content %}{% endblock %}
  13. </body>
  14. </html>
  • 使用block控制语句来定义派生模板可以插入代码的位置。 block被赋予一个唯一的名称,派生的模板可以在提供其内容时进行引用。
  • 简化模板index.html,基础模板base.html继承HTML元素
  1. {% extends "base.html" %}
  2. {% block content %}
  3. <h1>Hi, {{ user.username }}!</h1>
  4. {% for post in posts %}
  5. <div><p>{{ post.author.username }} says: <b>{{ post.body }}</b></p></div>
  6. {% endfor %}
  7. {% endblock %}