模板¶
您已经编写了应用程序的身份验证视图,但是如果您运行服务器并尝试访问任何 URL,您会看到 TemplateNotFound
错误。这是因为视图正在调用 render_template()
,但您尚未编写模板。模板文件将存储在 flaskr
包内的 templates
目录中。
模板是包含静态数据以及动态数据占位符的文件。模板使用特定数据进行渲染以生成最终文档。Flask 使用 Jinja 模板库来渲染模板。
在您的应用程序中,您将使用模板来渲染 HTML,它将在用户的浏览器中显示。在 Flask 中,Jinja 被配置为对在 HTML 模板中渲染的任何数据进行自动转义。这意味着渲染用户输入是安全的;他们输入的任何可能破坏 HTML 的字符,例如 <
和 >
,都将使用安全值进行转义,这些值在浏览器中看起来相同,但不会造成不良影响。
Jinja 的外观和行为与 Python 非常相似。特殊分隔符用于区分模板中的 Jinja 语法和静态数据。介于 {{
和 }}
之间的所有内容都是一个表达式,该表达式将输出到最终文档中。 {%
和 %}
表示控制流语句,如 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
在模板中自动可用。基于 g.user
是否设置(来自 load_logged_in_user
),将显示用户名和注销链接,或者显示注册和登录链接。 url_for()
也自动可用,用于生成视图的 URL,而不是手动编写它们。
在页面标题之后,在内容之前,模板循环遍历 get_flashed_messages()
返回的每条消息。你在视图中使用 flash()
来显示错误消息,这是将显示它们的代码。
此处定义了三个块,将在其他模板中覆盖它们
{% block title %}
将更改浏览器选项卡和窗口标题中显示的标题。{% block header %}
类似于title
,但将更改页面上显示的标题。{% 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
视图可以重定向到。
继续到 静态文件。