flask学习系列四--模板和静态文件

模板
之前我们为应用写了认证视图函数,但是如果我们运行程序来访问任意的url,会得到TemplateNotFound的错误。原因在于视图函数将会调用render_template()函数来渲染模板,但是我们现在还没有写模板。
模板被放在flaskr包的templates目录下。模板中包含有静态的数据(构建页面的HTML语句等)以及用于实现动态功能的占位符。模板通过一些特殊的数据被渲染,最终会生成一个文件。flask使用jinja模板库来渲染模板。

在应用中,我们将会使用模板来渲染HTML页面,这个HTML页面最终会显示在用户的浏览器上。flask中jinja被配置为自动忽略任何在HTML模板中被渲染的数据。这意味着在提交用户的输入时安全性得以保证。任何键入的字符都有可能干扰HTML页面的代码运行,such as < and > will be escaped with safe values that look the same in the browser but don’t cause unwanted effects.

jinja行为表现比较像python,特殊的分隔符用来区分jinja语法和模板文件中的静态数据。{{ }}里面的任何东西将会被输出到最终的文档中。{% %}表示一条控制流语句。与python不同的是,{ }是一个块的开始和结束标志,而非python中的缩进符。

基础布局
应用中的每个页面都会围绕一个不同的主体有一个相同的基本的布局。我们并不会在每个页面上再写一个重复的部分,而是采用每个页面都将会继承一个base页面的内容,然后覆盖特殊的部分。

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被设置的话(g.user在load_logged_in_user这个函数中被设置),要么已经登录的用户名和登出的链接被显示,否则登录的链接将会被显示。url_for()也是可以被直接调用的,它被用来为视图函数生成url。
在title部分后面,在content内容的前面有一个for循环语句,这个语句用于循环产生由get_flashed_message()函数所返回的信息。在视图函数中可以使用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块中,因此,窗口和页面会共用一个title。

输入标签在使用required属性,这将会告诉浏览器,如果没用内容的话,啥都不会提交。如果用户使用浏览器某些内置的东西发出请求的话,你可以考虑在flask的视图页面来验证数据是否合理。

登录
这个和注册时的模板是完全相同的,除了title和提交按钮之外。

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 %}

现在,认证的模板已经写好了,你可以尝试运行一下。

下面我们将学习静态文件部分。
认证视图和模板虽然已经工作,但是整个页面看起来很丑。可以使用静态文件将一些css样式添加到HTML布局中。
flask会自动添加一个静态视图,这个视图将会采用一个相对于flaskr/static目录的路径。base.html模板已经有了一个指向style.css文件的链接。

{{ url_for('static', filename='style.css') }}

除了css文件,其他格式的文件,例如.js文件,或者logo图标都可以放入这个文件中来。

flaskr/static/style.css

html { font-family: sans-serif; background: #eee; padding: 1rem; }
body { max-width: 960px; margin: 0 auto; background: white; }
h1 { font-family: serif; color: #377ba8; margin: 1rem 0; }
a { color: #377ba8; }
hr { border: none; border-top: 1px solid lightgray; }
nav { background: lightgray; display: flex; align-items: center; padding: 0 0.5rem; }
nav h1 { flex: auto; margin: 0; }
nav h1 a { text-decoration: none; padding: 0.25rem 0.5rem; }
nav ul  { display: flex; list-style: none; margin: 0; padding: 0; }
nav ul li a, nav ul li span, header .action { display: block; padding: 0.5rem; }
.content { padding: 0 1rem 1rem; }
.content > header { border-bottom: 1px solid lightgray; display: flex; align-items: flex-end; }
.content > header h1 { flex: auto; margin: 1rem 0 0.25rem 0; }
.flash { margin: 1em 0; padding: 1em; background: #cae6f6; border: 1px solid #377ba8; }
.post > header { display: flex; align-items: flex-end; font-size: 0.85em; }
.post > header > div:first-of-type { flex: auto; }
.post > header h1 { font-size: 1.5em; margin-bottom: 0; }
.post .about { color: slategray; font-style: italic; }
.post .body { white-space: pre-line; }
.content:last-child { margin-bottom: 0; }
.content form { margin: 1em 0; display: flex; flex-direction: column; }
.content label { font-weight: bold; margin-bottom: 0.5em; }
.content input, .content textarea { margin-bottom: 1em; }
.content textarea { min-height: 12em; resize: vertical; }
input.danger { color: #cc2f2e; }
input[type=submit] { align-self: start; min-width: 10em; }

这是我们本次的css代码。可以尝试运行看一看效果如何。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值