如需转载请注明出处。
win10 64位、Python 3.6.3、Notepad++、Chrome 67.0.3396.99(正式版本)(64 位)
注:作者编写时间2018-02-13,linux、python 3.5.2
以下内容均是加入自己的理解与增删,以记录学习过程。不限于翻译,部分不完全照搬作者Miguel Grinberg的博客,版权属于作者,感谢他提供免费学习的资料。
传送门 | |||
---|---|---|---|
00 开篇 | 01 Hello world | 02 模板 | 03 Web表单 |
04 数据库 | 05 用户登录 | 06 个人资料和头像 | 07 错误处理 |
08 关注 | 09 分页 | 10 支持QQ邮箱 | 11 美化页面 |
12 时间和日期 | 13 I18n和L10n 翻译成中文 zh-CN | 14 Ajax(百度翻译API | 15 更好的App结构(蓝图) |
16 全文搜索 | 17 部署到腾讯云Ubuntu | 18 部署到Heroku | 19 部署到Docker容器 |
20 JavaScript魔法 | 21 用户通知 | 22 后台工作(Redis) | 23 应用程序编程接口(API) |
这个Microblog应用程序已有一段时间了,或许已经注意到,并没有花时间来美化它的页面。所有的模板是使用的基础样式,没有自定义样式。这对于我们来说非常有用,可以专注于应用程序的实际逻辑,不用分心去编写好看的HTML和CSS代码。
目前已经专注于应用程序的后端部分有一段时间了。因此,本章将暂停一下,并花一些时间来学习 如何使应用程序看起来更加精致、专业。
本章将与之前的章节略有不同,因为不会像往常那样详细地关注Python方面。创建漂亮的网页是一个很大的主题,而与Python web后端开发很大程度上无关,因此将讨论一些基本指导和想法,将重新设计应用的外观来研究和学习它。
如果你像我一样,只是一个想创建规范网页的开发人员,没有时间或兴趣去学习底层机制,并通过编写原生HTML和CSS来实现它,那么唯一可行的解决方案是使用CSS框架来简化任务。通过这条路径,将失去一些操作自由,但另一方面,我们的网页在所有浏览器中会看起来很不错,而也不需要花费太多精力。CSS框架为普通类型的用户界面元素提供了高级CSS类的集合,其中包含预定义样式。这些框架中的大多数还为 不能使用HTML和CSS严格执行的操作提供JavaScript插件。
最受欢迎的一个CSS框架是由Twitter建立的Bootstrap。如果想看使用这个框架设计的页面类型,可查看文档中的示例。
使用Bootstrap为网页设置样式的好处:
使用Bootstrap最直接方法是在基础模板中导入 bootstrap.min.css文件。可以下载这个文件副本,并将其添加到项目中;也可以直接从CDN导入(这里查看)。然后,可以根据文档开始使用它提供的通用CSS类。还可以导入包含框架JavaScript代码的bootstrap.min.js文件,以便使用更高级的功能。
幸运的是,有一个名为 Flask-Bootstrap的Flask扩展,它提供一个随时可用的基本模板,它安装了Bootstrap框架。安装这个扩展:版本3.3.7.1;附带安装dominate 2.3.1(用于使用优雅的DOM API创建和操作HTML文档)、visitor 0.1.3(一个微型Pythonic访客实现)。
(venv) D:\microblog>pip install flask-bootstrap
Collecting flask-bootstrap
Using cached https://files.pythonhosted.org/packages/88/53/958ce7c2aa26280b7fd7f3eecbf13053f1302ee2acb1db58ef32e1c23c2a/Flask-Bootstrap-3.3.7.1.tar.gz
Requirement already satisfied: Flask>=0.8 in d:\microblog\venv\lib\site-packages (from flask-bootstrap)
Collecting dominate (from flask-bootstrap)
Using cached https://files.pythonhosted.org/packages/43/b2/3b7d67dd59dab93ae08569384b254323516e8868b453eea5614a53835baf/dominate-2.3.1.tar.gz
Collecting visitor (from flask-bootstrap)
Using cached https://files.pythonhosted.org/packages/d7/58/785fcd6de4210049da5fafe62301b197f044f3835393594be368547142b0/visitor-0.1.3.tar.gz
Requirement already satisfied: click>=5.1 in d:\microblog\venv\lib\site-packages (from Flask>=0.8->flask-bootstrap)
Requirement already satisfied: itsdangerous>=0.24 in d:\microblog\venv\lib\site-packages (from Flask>=0.8->flask-bootstrap)
Requirement already satisfied: Werkzeug>=0.14 in d:\microblog\venv\lib\site-packages (from Flask>=0.8->flask-bootstrap)
Requirement already satisfied: Jinja2>=2.10 in d:\microblog\venv\lib\site-packages (from Flask>=0.8->flask-bootstrap)
Requirement already satisfied: MarkupSafe>=0.23 in d:\microblog\venv\lib\site-packages (from Jinja2>=2.10->Flask>=0.8->flask-bootstrap)
Installing collected packages: dominate, visitor, flask-bootstrap
Running setup.py install for dominate ... done
Running setup.py install for visitor ... done
Running setup.py install for flask-bootstrap ... done
Successfully installed dominate-2.3.1 flask-bootstrap-3.3.7.1 visitor-0.1.3
app/__init__.py:添加Flask-Bootstrap实例
# ...
from flask_bootstrap import Bootstrap
app = Flask(__name__)
# ...
mail = Mail(app)
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基础模板继承。
app/templates/base.html:重新设计基础模板
{% extends "bootstrap/base.html" %}
{% block title %}
{% if title %}
{{ title }} - Microblog
{% else %}
Welcome to Microblog
{% endif %}
{% endblock %}
{% block navbar %}
{% endblock %}
{% block content %}
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %}
{% endwith %}
{# application content needs to be provided in the app_content block #}
{% block app_content %}{% endblock %}
{% endblock %}
在上述代码中,可看到如何从bootstrap/base.html
派生这个模板,然后分别实现页面标题、导航栏、页面内容 三个块。
title 块
使用
标签 定义将用于页面标题的文本。对于个块,只是移动了在原始基础模板中
标签内的逻辑。
navbar 块
是可选块,可用于定义导航栏。对于这个块,在Bootstrap导航栏文档中的改写了这个示例,以便它在左端包含站点标记,接着是 Home 和Explore链接。然后,添加了与页面右边框对齐的Profile和Login或Logout链接。
最后,在content块
中定义了一个顶级容器,在其中编写了渲染 闪烁消息的逻辑,现在它们显示为Bootstrap警报。接着是一个新的app_content块
,它被定义为 只有派生模板才能定义它们自己的内容。
所有页面模板的原始版本 都在名为content
的块中定义它们的内容。如上所示,名为content
的块被Flask-Bootstrap所使用,因此将内容块 重命名为app_content
。所以,我们所有的模板都必须重命名才能去使用app_content块 作为它们的内容块。例如,如下是404.html
模板 如何修改版本的演示:
{% extends "base.html" %}
{% block app_content %}
File Not Found
{% endblock %}
剩余的所有其他模板一一按上例修改即可。
下方将看到重新设计的register.html
模板作为一个示例:
app/templates/register.html:
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
Register
{{ wtf.quick_form(form) }}
{% endblock %}
上述代码中,在顶部声明的import
工作原理与在模板上边的一个Python import
类似。这还添加了一个wtf.quick_form()
宏,它在一行简单代码中呈现完整的表单,包括支持显示验证错误,并且所有样式都适合Bootstrap框架。
以下展示为应用程序中的其他表单
所做的更改:
app/templates/edit_profile.html
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
Edit Profile
{{ wtf.quick_form(form) }}
{% endblock %}
app/templates/index.html
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
Hello,{{ current_user.username }}!
{% if form %}
{{ wtf.quick_form(form) }}
{% endif %}
{% for post in posts %}
{% include '_post.html' %}
{% endfor %}
{% endblock %}
app/templates/login.html
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
Sign In
{{ wtf.quick_form(form) }}
New User? Click to Register!
Forgot Your Password?
Click to Reset It
{% endblock %}
app/templates/reset_password.html
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
Reset Your Password
{{ wtf.quick_form(form) }}
{% endblock %}
app/templates/reset_password_request.html
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
Reset Password
{{ wtf.quick_form(form) }}
{% endblock %}
app/templates/user.html
{% extends "base.html" %}
{% block app_content %}
 }})
User:{{ user.username }}
{% if user.about_me %}
{{ user.about_me }}
{% endif %}
{% if user.last_seen %}
Last seen on:{{ user.last_seen }}
{% endif %}
{% if user == current_user %}
{% elif not current_user.is_following(user) %}
{% else %}
{% endif %}
{% for post in posts %}
{% include '_post.html' %}
{% endfor%}
{% endblock%}
{{ post.author.username }}
says:
{{ post.body }}
{% endblock %}
不过注意,在上述实现中,当某个方向没有更多内容时,将运用禁用状态,而不是隐藏下一个或上一个链接,这将使链接显示为灰色。
类似的更改也需要运用于`user.html`,这个更改在上一小节上展示了。
最终效果呈现:

目前为止,项目结构:
microblog/
app/
templates/
email/
reset_password.html
reset_password.txt
_post.html
404.html
500.html
base.html
edit_profile.html
index.html
login.html
register.html
reset_password.html
reset_password_request.html
user.html
__init__.py
email.py
errors.py
forms.py
models.py
routes.py
logs/
microblog.log
migrations/
venv/
app.db
config.py
microblog.py
tests.py
参考:
[作者博客](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xi-facelift)
如需转载请注明出处。