模板

您已经为您的应用程序编写了身份验证视图,但是如果您正在运行服务器并尝试访问任何 URL,您会看到一个 TemplateNotFound 错误。那是因为视图正在调用 render_template(),但是您还没有编写模板。模板文件将存储在 flaskr 包内的 templates 目录中。

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

在您的应用程序中,您将使用模板来渲染 HTML,这将显示在用户的浏览器中。在 Flask 中,Jinja 被配置为自动转义在 HTML 模板中渲染的任何数据。这意味着渲染用户输入是安全的;他们输入的任何可能干扰 HTML 的字符,例如 <> 将被转义安全值,这些值在浏览器中看起来相同,但不会引起不良影响。

Jinja 的外观和行为主要类似于 Python。特殊的定界符用于区分 Jinja 语法和模板中的静态数据。{{}} 之间的任何内容都是将输出到最终文档的表达式。{%%} 表示控制流语句,例如 iffor。与 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 在模板中自动可用。根据是否设置了 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 %} 内。这将设置标题块,然后将其值输出到标题块中,以便窗口和页面共享相同的标题,而无需编写两次。

input 标签在这里使用了 required 属性。这告诉浏览器在填写这些字段之前不要提交表单。如果用户使用的是不支持该属性的旧浏览器,或者他们正在使用浏览器以外的东西来发出请求,您仍然希望在 Flask 视图中验证数据。即使客户端也进行了一些验证,在服务器上始终完全验证数据也很重要。

登录

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

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 视图。

继续阅读 静态文件