模板

应用已经写好验证视图,但是如果现在运行服务器的话,无论访问哪个 URL,都会看到一个TemplateNotFound 错误。这是因为视图调用了 render_template(),但是模板还没有写。模板文件会储存在 flaskr包内的 templates 文件夹内。

模板是包含静态数据和动态数据占位符的文件。使用特定数据呈现模板以生成最终文档。Flask使用 Jinja 模板库来渲染模板。

在教程的应用中会使用模板来渲染显示在用户浏览器中的 HTML 。在 Flask 中,Jinja 被配置为 自动转义 HTML 模板中的任何数据。即渲染用户的输入是安全的。任何用户输入的可能出现歧意的字符,如 < and > ,会被 转义 ,替换为 安全 的值。这些值在浏览器中看起来一样,但是没有副作用。

Jinja 看上去并且运行地很像 Python 。Jinja 语句与模板中的静态数据通过特定的 分界符分隔。任何位于 {{ and }}``这间的东西是一个会输出到最终文档的静态式。``{% and %} 之间的东西表示流程控制语句,如 if 和 for 。与 Python 不同,代码块使用分界符分隔,而不是使用缩进分隔。因为代码块内的静态文本可以会改变缩进。

基础布局

应用程序中的每个页面将在不同的主体周围具有相同的基本布局。每个模板会 扩展 同一个基础模板并重载相应的小节,而不是重写整个HTML 结构。

flaskr/templates/base.html
<!doctype html>
<title>{% block title %}{% endblock %} - Flaskr</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<nav>
  <h1>Flaskr</h1>
  <ul>
    {% if g.user %}
      <li><span>{{ g.user['username'] }}</span>
      <li><a href="{{ url_for('auth.logout') }}">Log Out</a>
    {% else %}
      <li><a href="{{ url_for('auth.register') }}">Register</a>
      <li><a href="{{ url_for('auth.login') }}">Log In</a>
    {% endif %}
  </ul>
</nav>
<section class="content">
  <header>
    {% block header %}{% endblock %}
  </header>
  {% for message in get_flashed_messages() %}
    <div class="flash">{{ message }}</div>
  {% endfor %}
  {% block content %}{% endblock %}
</section>

g 在模板中自动可用。基于IF g.user 被设置(从 load_logged_in_user ),显示用户名和注销链接,或显示注册和登录链接。 url_for() 也是自动可用的,用于生成视图的URL,而不是手动将其写出。

在页面标题之后和内容之前,模板会循环显示get_flashed_messages() 返回的每个消息。在视图中使用 flash() 来处理出错信息,在模板中就可以这样显示出来。

此处定义的三个块将在其他模板中被重写:

  1. {{% block title %}} 将更改浏览器选项卡和窗口标题中显示的标题。

  2. {{% block header %}} 类似于 title 但会更改页面上显示的标题。

  3. {{% block content %}} 是每个页面的内容的位置,例如登录表单或博客文章。

基本模板直接位于 templates 文件夹内。为了使其他模板保持有序,蓝图的模板将放在与蓝图同名的文件夹中。

注册

flaskr/templates/auth/register.html
{% extends 'base.html' %}

{% block header %}
  <h1>{% block title %}Register{% endblock %}</h1>
{% endblock %}

{% block content %}
  <form method="post">
    <label for="username">Username</label>
    <input name="username" id="username" required>
    <label for="password">Password</label>
    <input type="password" name="password" id="password" required>
    <input type="submit" value="Register">
  </form>
{% endblock %}

{{% extends 'base.html' %}} 告诉Jinja此模板应替换基模板中的块。所有替换的内容必须位于 {% block %} 标签之内。

一个实用的模式是把 {% block title %} 放在 {% block header %} 内部。 这里不但可以设置 title 块,还可以把其值作为 header 块的内容, 一举两得。

这个 input 标签使用了 required 属性。这会告诉浏览器在填写这些字段之前不要提交表单。如果用户使用的是不支持该属性的旧浏览器,或者他们使用浏览器之外的某个工具进行请求,那么你还是要在视图中验证输入数据。必须始终完全验证服务器上的数据,即使客户端也进行了一些验证。

登录

本模板除了标题和提交按钮外与注册模板相同。

flaskr/templates/auth/login.html
{% extends 'base.html' %}

{% block header %}
  <h1>{% block title %}Log In{% endblock %}</h1>
{% endblock %}

{% block content %}
  <form method="post">
    <label for="username">Username</label>
    <input name="username" id="username" required>
    <label for="password">Password</label>
    <input type="password" name="password" id="password" required>
    <input type="submit" value="Log In">
  </form>
{% endblock %}

注册用户

既然编写了身份验证模板,就可以注册用户了。请确定服务器还在运行(如果没有请使用 flask run),然后 访问 http://127.0.0.1:5000/auth/register

尝试单击“注册”按钮而不填写表单,并查看浏览器是否显示错误消息。尝试在 register.html 中删除 required 属性并再次单击“注册”。页面会重载并显示来自于视图中的 flash() 的出错信息,而不是浏览器显示出错信息。

填写用户名和密码,你将被重定向到登录页面。请尝试输入错误的用户名,或输入正确的用户名和错误的密码。如果登录成功,那么会看到一个出错信息,因为还没有写登录后要转向的 index 视图。

下面请阅读 静态文件 。