最近在Flask Web Development作者博客看到第二版Flask Mega-Tutorial已在2017年底更新,现翻译给大家参考,希望帮助大家学习flask。
这是Flask Mega-Tutorial系列的第十一章,其中我将告诉您如何使用基于Bootstrap用户界面框架的新模板替换基本HTML模板。
供您参考,以下是本系列文章的列表。
- 第1章:Hello, World!
- 第2章:模板
- 第3章:Web表单
- 第4章:数据库
- 第5章:用户登录
- 第6章:配置文件页面和头像
- 第7章:错误处理
- 第8章:关注与被关注
- 第9章:分页
- 第10章:电子邮件支持
- 第11章:整容(本文)
- 第12章:日期和时间
- 第13章:I18n和L10n
- 第14章:Ajax
- 第15章:大型应用程序结构
- 第16章:全文搜索
- 第17章:在Linux上部署
- 第18章:在Heroku上部署
- 第19章:Docker容器上的部署
- 第20章:一些JavaScript Magic
- 第21章:用户通知
- 第22章:后台工作
- 第23章:应用程序编程接口(API)
你把玩Microblog应用程序已经有一段时间了,所以我确定你注意到我没有花太多时间美化它,或者更具体地说,我没有花时间在那上面。所有的模板只使用了基础样式,绝对没有自定义样式。对我来说,专注于应用程序的实际逻辑是很有用的,因为不会分心去编写好看的HTML和CSS的代码。
但是我现在专注于这个应用程序的后端部分已经有一段时间。因此,在本章中我将暂停一下,并将花一些时间向您展示如何使应用程序看起来更加优雅和专业。
本章将与之前的章节略有不同,因为我不会像往常解说Python那样,事无巨细,毕竟Python才是本教程的主要内容。创建漂亮的网页是一个很大的主题,与Python Web后端开发很大程度上无关,但我将讨论如何处理前端的一些基本指导和想法,并且您还将通过重新设计外观来研究和学习它。
CSS框架
虽然我们可以说写代码很难,但与网页设计师相比,我们的痛苦是无足轻重的,他们必须在所有的网络浏览器上编写具有良好和一致外观的模板。虽然它近年来这种情况得到一定程度的缓解,但是在某些浏览器中仍然存在一些模糊的错误或奇怪的设定,这使得设计网页的任务变得非常困难。如果您还需要兼容屏幕限制设备(如平板电脑和智能手机)的浏览器,这将更加困难。
如果你像我一样,是一个只想创建出规范网页的开发人员,但没有时间或兴趣去学习底层机制,并通过编写原生HTML和CSS来有效实现它,那么唯一可行的解决方案是使用CSS框架来简化任务。通过这条方式,您将失去一些创造性的自由,但另一方面,您的网页在所有浏览器中看起来都会很好,而又不需要花费太多精力。CSS框架提供了一组高级CSS类,其中包含用于常见类型的用户界面元素的预定义样式。大多数这样的框架还提供JavaScript组件,以实现不能纯粹使用HTML和CSS来完成的功能。
介绍Bootstrap
最受欢迎的CSS框架之一是由Twitter推出的Bootstrap。如果您想看看这个框架可以设计的页面类型,那么文档中有一些示例。
以下是使用Bootstrap为您的网页设置样式的一些好处:
- 在所有主流Web浏览器中都有相似的外观
- 自适应PC,平板电脑和手机屏幕尺寸
- 可定制的布局
- 风格精美的导航栏、表单、按钮,提醒、弹出窗口等。
使用Bootstrap的最直接方法是在基本模板中导入bootstrap.min.css文件。您可以下载此文件的副本并将其添加到项目中,也可以直接从CDN导入。然后你可以根据文档开始使用它提供的通用CSS类,实在是太棒了。您可能还想导入包含JavaScript框架代码的bootstrap.min.js文件,以便您也可以使用最高级的功能。
幸运的是,有一个名为Flask-Bootstrap的Flask扩展,它提供了一个开箱即用的基本模板,该模板引入了Bootstrap框架。让我们安装此扩展程序:
(venv) $ pip install flask-bootstrap
使用Flask-Bootstrap
Flask-Bootstrap需要像大多数其他Flask扩展一样进行初始化:
# app/__init__.py: Flask-Bootstrap instance.
# ...
from flask_bootstrap import Bootstrap
app = Flask(__name__)
# ...
bootstrap = Bootstrap(app)
初始化扩展后,bootstrap / base.html模板变为可用状态,并且可以使用
extends
子句从应用程序模板中引用。
但是你记得,我已经使用了extends
子句来继承我的基础模板,这允许我将页面的公共部分放在一个地方。我在base.html模板定义了导航栏,其中包含一些链接,还导出了一个content
块。应用程序中的所有其他模板都从基本模板继承,并向content
块提供页面的主要内容。
那么我如何适配Bootstrap基础模板呢?其思想是使用一个三级层次结构而不是仅仅使用两层层次结构。bootstrap/base.html文件模板提供页面的基本结构,其中包括Bootstrap框架文件。这个模板导出了一些用于派生模板(如title
,navbar
和content
)的块(请参阅块的完整列表)。我要更改base.html文件模板,让它继承bootstrap/base.html文件,并提供title
,navbar
和content
块。反过来,base.html将为从其派生的模板导出app_content
块以定义页面内容。
下面你可以看看修改base.html后,它是如何从Bootstrap基础模板继承。请注意,此列表不包含导航栏的整个HTML,但您可以在GitHub上看到完整的实现,也可以下载本章的代码
<!-- app/templates/base.html: Redesigned base template. -->
{% extends 'bootstrap/base.html' %}
{% block title %}
{% if title %}{{ title }} - Microblog{% else %}Welcome to Microblog{% endif %}
{% endblock %}
{% block navbar %}
<nav class="navbar navbar-default">
... navigation bar here (see complete code on GitHub) ...
</nav>
{% endblock %}
{% block content %}
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-info" role="alert">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{# application content needs to be provided in the app_content block #}
{% block app_content %}{% endblock %}
</div>
{% endblock %}
在这里,您可以看到我如何从bootstrap/base.html派生此模板,然后分别实现页面标题,导航栏和页面内容的三个模板。
title
块需要使用<title>
标签来定义用于页面标题的文本。对于这个块,我只是移动了原始基本模板中<title>
标签内的逻辑。
navbar
块是可选块,可用于定义导航栏。对于这个块,我调整了Bootstrap导航栏文档中的示例,以便它在左侧展示网站品牌,跟着是Home和Explore链接。然后,我添加了个人主页和登录/注销链接并使其与页面右边框对齐。如上所述,我在上面的示例中省略了HTML,但您可以从本章的下载包中获取完整的base.html模板。
最后,在content
块中我定义了一个顶级容器,在其中我有渲染闪存消息的逻辑,现在它们将显示为Bootstrap警报的样式。接下来是一个新的app_content
块,它被定义为只有派生模板才能定义自己的内容。
所有页面模板的原始版本都在名为content
的块中定义了它们的内容。如上所示,Flask-Bootstrap使用名为content
的块,因此我将内容块重命名为app_content
。所以我的所有模板都必须重命名才能使用app_content
作为它们的内容块。例如,这是404.html模板的修改后版本的展示:
<!-- app/templates/404.html: Redesigned 404 error template. -->
{% extends "base.html" %}
{% block app_content %}
<h1>File Not Found</h1>
<p><a href="{{ url_for('index') }}">Back</a></p>
{% endblock %}
渲染Bootstrap表单
Flask-Bootstrap的一个很棒的工作就是渲染表格。Flask-Bootstrap不是必须逐个设置表单字段的样式,而是使用一个接受Flask-WTF表单对象作为参数的宏,并使用Bootstrap样式渲染出完整的表单。
您可以在下面看到重新设计的register.html模板:
<!-- app/templates/register.html: User registration template. -->
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<h1>Register</h1>
<div class="row">
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
</div>
{% endblock %}
是不是很棒?顶部附近的import
声明与Python导入类似。这增加了一个wtf.quick_form()
宏,在一行代码中渲染了完整的表单,包括显示验证错误的支持,并且适配Bootstrap框架的所有样式。
再一次,我不会向您展示我为应用程序中的其他表单所做的所有更改,但这些更改都是在您可以在GitHub上下载或检查到的。
渲染博客帖子
渲染单个博客帖子的逻辑被提取到名为_post.html的子模板。我需要对此模板进行一些小的调整,以便在Bootstrap下看起来很好。
<!-- app/templates/_post.html: Redesigned post sub-template. -->
<table class="table table-hover">
<tr>
<td width="70px">
<a href="{{ url_for('user', username=post.author.username) }}">
<img src="{{ post.author.avatar(70) }}" />
</a>
</td>
<td>
<a href="{{ url_for('user', username=post.author.username) }}">
{{ post.author.username }}
</a>
says:
<br>
{{ post.body }}
</td>
</tr>
</table>
渲染分页链接
分页链接是Bootstrap提供直接支持的另一个领域。为此,我再一次查看Bootstrap 文档并修改其中一个示例。
以下是index.html页面中的内容:
<!-- app/templates/index.html: Redesigned pagination links. -->
...
<nav aria-label="...">
<ul class="pager">
<li class="previous{% if not prev_url %} disabled{% endif %}">
<a href="{{ prev_url or '#' }}">
<span aria-hidden="true">←</span> Newer posts
</a>
</li>
<li class="next{% if not next_url %} disabled{% endif %}">
<a href="{{ next_url or '#' }}">
Older posts <span aria-hidden="true">→</span>
</a>
</li>
</ul>
</nav>
请注意,在这个实现中,当下一页或上一页方向上没有更多内容时,我将应用禁用状态,而不是隐藏下一页或上一页链接,这将使链接显示为灰色。
类似的更改需要应用于user.html,我不会在这里展示它。本章的下载包包含这些更改。
对比更改前后
要使用这些更改来更新您的应用程序,请下载本章的zip文件并相应地更新您的模板。
下面你可以对比几张美化前后的图片来观察转变情况。请记住,在不更改一行应用程序逻辑的情况下实现了此更改!
原文链接:https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xi-facelift