Flask 教程 第十一章:美化
本文翻译自The Flask Mega-Tutorial Part XI: Facelift
这是Flask Mega-Tutorial系列的第十一部分,我将告诉你如何用基于Bootstrap用户界面框架的新模板替换基础的HTML模板。
你把玩Microblog应用也有一段时间了,所以我相信你已经注意到,我没有花太多时间来美化它,说得更具体点,我根本没有花时间。 所有的模板只使用了基础样式,没有任何自定义的展现。 这对于我来说却非常有用,因为我可以专注于应用的实际逻辑,不用分心于编写好看的HTML和CSS代码。
但是我已经长期关注应用的后端部分一段时间了。 因此在本章中,我暂停一下后端的工作,并花点时间向你展示如何使应用看起来更加优雅和专业。
本章将与之前的章节略有不同,因为我不会像平常解说Python那样,事无巨细,一一道来,毕竟Python才是本教程的主要内容。 创建漂亮的网页是一个很广泛的话题,而与Python Web的后端开发很大程度上无关,因此我将讨论一些基本的指导方针和想法,你可以通过重新设计应用的外观来研究和学习它。
本章的GitHub链接为:Browse, Zip, Diff.
CSS框架
虽然我们可以争辩说写代码不容易,但是与那些必须让网页在所有Web浏览器上具有良好一致外观的网页设计师相比,我们的痛苦不值一提。 虽然近年来这种情况得到一定程度的缓解,但是在一些浏览器中仍然存在着晦涩的错误或奇怪的设定,这使得设计网页的任务变得非常困难。 如果还需要兼容屏幕限制设备(诸如平板电脑和智能手机)的浏览器,则更加困难。
如果你和我一样,只是一个想创建出规范网页的开发人员,没有时间或兴趣去学习底层机制并通过编写原生HTML和CSS来实现它,那么唯一可行的解决方案是使用CSS框架来简化任务。 通过这种方式,你会失去一些创造性的自由,但另一方面,无需通过太多的功夫就可以让网页在所有浏览器中看起来都不错。 CSS框架为普通类型的用户界面元素提供了高级CSS类的集合,其中包含预定义样式。 大多数这样的框架还提供JavaScript插件,以实现不能纯粹使用HTML和CSS来完成的功能。
Bootstrap简介
最受欢迎的CSS框架之一是由Twitter推出的Bootstrap。 如果你想看看这个框架可以设计的页面类型,文档有一些示例。
这些是使用Bootstrap来设置网页风格的一些好处:
- 在所有主流网页浏览器中都有相似的外观
- 自动处理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实例。
- # ...
- from flask_bootstrap import Bootstrap
- app = Flask(__name__)
- # ...
- bootstrap = Bootstrap(app)
在初始化插件之后,bootstrap/base.html模板就会变为可用状态,你可以使用extends
子句从应用模板中引用。
但是,回顾一下,我已经使用了extends
子句来继承我的基础模板,这使我可以将页面的公共部分放在一个地方。 base.html模板定义了导航栏,其中包含几个链接,并且还导出了一个content
块。 应用中的所有其他模板都从基础模板继承,并为内容块提供页面的主要内容。
那么我怎样才能适配Bootstrap基础模板呢? 解决方案是从使用两个层级到使用三个层级。 bootstrap/base.html模板提供页面的基本结构,其中引入了Bootstrap框架文件。 这个模板为派生的模板定义了一些块,例如title
,navbar
和content
(参见块的完整列表)。 我将更改base.html模板以从bootstrap/base.html派生,并提供title
,navbar
和content
块的实现。 反过来,base.html将为从其派生的模板导出app_content
块以定义页面内容。
下面你可以看到从Bootstrap基础模板派生的base.html的代码。 请注意,此列表不包含导航栏的整个HTML,但你可以在GitHub上或下载本章的代码来查看完整的实现。
app/templates/base.html:重新设计后的基础模板。
- {% 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:重新设计后的404错误模板。
- {% 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::用户注册模板。
- {% 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: 重新设计后的用户动态子模板。
- <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: 重新设计后的分页链接。
- ...
- <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文件并更新应用。
下面你可以对照几张美化前后的图片来观察转变情况。 请记住,这种转变是在不改变一行应用逻辑代码的情况下实现的!
Flask 教程 第十一章:美化的更多相关文章
- Flask 教程 第二十一章:用户通知
本文翻译自The Flask Mega-Tutorial Part XXI: User Notifications 这是Flask Mega-Tutorial系列的第二十一章,我将添加一个私有消息功能 ...
- 2017.2.15 开涛shiro教程-第二十一章-授予身份与切换身份(二) controller
原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 开涛shiro教程-第二十一章-授予身份与切换身份(二) 1.回顾 ...
- 2017.2.15 开涛shiro教程-第二十一章-授予身份与切换身份(一) table、entity、service、dao
原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 第二十一章 授予身份与切换身份(一) 1.使用场景 某个领导因为某 ...
- python 教程 第二十一章、 扩展Python
第二十一章. 扩展Python /* D:\Python27\Lib\Extest-1.0\Extest2.c */ #include <stdio.h> #include <std ...
- python 教程 第十一章、 异常
第十一章. 异常 1) try/except/else格式 try: s = raw_input('--> ') except EOFError: print 'Why did you d ...
- Flask 教程 第四章:数据库
本文翻译自 The Flask Mega-Tutorial Part IV: Database 在Flask Mega-Tutorial系列的第四部分,我将告诉你如何使用数据库. 本章的主题是重中之重 ...
- Flask 教程 第十七章:Linux上的部署
本文翻译自The Flask Mega-Tutorial Part XVII: Deployment on Linux 这是Flask Mega-Tutorial系列的第十七部分,我将把Microbl ...
- Flask 教程 第十三章:国际化和本地化
本文翻译自The Flask Mega-Tutorial Part XIII: I18n and L10n 这是Flask Mega-Tutorial系列的第十三部分,我将告诉你如何扩展Microbl ...
- Flask 教程 第七章:错误处理
本文翻译自The Flask Mega-Tutorial Part VII: Error Handling 这是Flask Mega-Tutorial系列的第七部分,我将告诉你如何在Flask应用中进 ...
随机推荐
- mysql主从架构搭建
1.配置文件,开启二进制日志 vim /etc/my.cnf 在mysql下增加如下内容 server-id= log-bin=mysql-bin relay-log=mysql-relay 2.登录 ...
- Nacos集群配置实例(windows下测试)
1.首先 fork 一份 nacos 的代码到自己的 github 库,然后把代码 clone 到本地. git地址:https://github.com/alibaba/nacos.git 2.然后 ...
- 高质量iOS博客推荐
https://www.jianshu.com/p/ea9fabdc12ed 原文地址 原作者记录了一些高质量ios博客地址,本文只做收藏使用.
- 使用Cocoapods创建私有podspec
Cocoapods是非常好用的一个iOS依赖管理工具,使用它可以方便的管理和更新项目中所使用到的第三方库,以及将自己的项目中的公共组件交由它去管理.Cocoapods的介绍及优点本文就不在赘述,我开始 ...
- 谈架构设计中DDD思想的运用
首先,描述一下我的业务场景及项目分层结构,非标准DDD(其实我不觉得有标准),只是思考的时候有带入DDD思想. 业务场景:这是一个ERP系统对中台提供的接口项目,仓储操作大多都是存储过程去完成的. 项 ...
- Java instanceof 和 Class.isInstance()区别与应用
一.instanceof 关键字 instanceof 关键字用于判断某个实例是否是某个类的实例化对象,形如: String.class instanceof Class "test&quo ...
- spring源码学习之设计模式(1)单例模式
众所周知,单例模式分为饿汉式和懒汉式,昨天在看了<spring5核心原理与30个类手写实战>之后才知道饿汉式有很多种写法,分别适用于不同场景,避免反射,线程不安全问题.下面就各种场景.采用 ...
- 在VS2017中连接到SQLite数据源(dbfist)
在VS2017中配置.连接到SQLite数据源(dbfist) 需要安装的VS插件 SQLite/SQL Server Compact ToolBox 这个插件安装后,在选择数据源时已经可以选择SQL ...
- 一篇文章让你明白CPU缓存一致性协议MESI
CPU高速缓存(Cache Memory) CPU为何要有高速缓存 CPU在摩尔定律的指导下以每18个月翻一番的速度在发展,然而内存和硬盘的发展速度远远不及CPU.这就造成了高性能能的内存和硬盘价格及 ...
- 在Atmel Studio7中创建ASF项目
使用ASF自带例程的方式创建程序是很方便,但是因为系统例程支持的ATMEL开发板往往和用户板配置不同,所以我们需要自己创建项目.下面介绍在AS7.0中快速创建一个ASF项目的方法. 1.首先从菜单开始 ...