Flask入门教程实例:搭建一个静态博客


Posted in Python onMarch 27, 2015

现在流行的静态博客/网站生成工具有很多,比如 Jekyll, Pelican, Middleman, Hyde 等等,StaticGen 列出了目前最流行的一些静态网站生成工具。

我们的内部工具由 Python/Flask/MongoDB 搭建,现在需要加上文档功能,写作格式是 Markdown,不想把文档放到数据库里,也不想再弄一套静态博客工具来管理文档,于是找到了 Flask-FlatPages 这个好用的 Flask 模块。熟悉 Flask 的同学花几分钟的时间就可以用搭建一个简单博客,加上 Bootstrap 的帮助,不到一小时内就可以用 Flask-Flatpages 弄个像模像样的网站出来。

创建开发环境

首先我们需要 pip,在 Mac 上最简单的安装办法是:

$ sudo easy_install pip

$ sudo easy_install virtualenv

如果你在 Mac 上用 Homebrew 包管理工具的话的话,也可以用 brew 升级 Python 和安装 pip:
$ brew update

$ brew install python

创建一个 blog 目录、生成 Python 独立虚拟环境并在这个环境里安装需要的 Flask, Flask-FlatPages 模块:
$ mkdir blog

$ cd blog
$ virtualenv flask

New python executable in flask/bin/python

Installing setuptools, pip...done.
$ flask/bin/pip install flask

$ flask/bin/pip install flask-flatpages

在 blog 目录下我们分别新建几个目录:static 用来存放 css/js 等文件,templates 用来存放 flask 要用的 Jinja2 模版,pages 用来存放我们静态博客(Markdown 格式):
$ mkdir -p app/static app/templates app/pages

程序

主程序 blog.py 的功能是,导入必要的模块、配置 Flask-FlatPages 模块需要的参数、创建 Flask 应用、写几个 URL 路由函数,最后运行这个应用:

$ vi app/blog.py

#!flask/bin/python

from flask import Flask, render_template

from flask_flatpages import FlatPages
DEBUG = True

FLATPAGES_AUTO_RELOAD = DEBUG

FLATPAGES_EXTENSION = '.md'
app = Flask(__name__)

app.config.from_object(__name__)

flatpages = FlatPages(app)
@app.route('/')

def index():

    pages = (p for p in flatpages if 'date' in p.meta)

    return render_template('index.html', pages=pages)
@app.route('/pages/<path:path>/')

def page(path):

    page = flatpages.get_or_404(path)

    return render_template('page.html', page=page)
if __name__ == '__main__':

    app.run(port=8000)

模版

在 Python 中直接生成 HTML 很繁琐并不好玩(那是上个世纪90年代的 PHP 搞的事情),在现代社会,我们使用模版引擎,Flask 已经自动配置好了 Jinja2 模版,使用方法 render_template() 来渲染模版就可以了。Flask 会默认在 templates 目录里中寻找模版,我们只需要创建几个模版文件就可以了,这里我们创建 base.html, index.html 和 page.html.

$ vi app/templates/base.html

<!doctype html>

<html>

<head>

    <meta charset="utf-8">

    <title>vpsee.com static blog</title>

</head>
<body>

    <h1><a href="{{ url_for("index") }}">vpsee.com blog</a></h1>

    {% block content %}

    {% endblock content %}

</body>

</html>

代码里 extends “base.html” 的意思是从 base.html 里继承基本的 “骨架”。
$ vi app/templates/index.html

{% extends "base.html" %}
{% block content %}

    <h2>List of pages

    <ul>

        {% for page in pages %}

        <li>

            <a href="{{ url_for("page", path=page.path) }}">{{ page.title }}</a>

        </li>

        {% else %}

        <li>No post.</li>

        {% endfor %}

    </ul>

{% endblock content %}

$ vi app/templates/page.html

{% extends "base.html" %}
{% block content %}

    <h2>{{ page.title }}</h2>

    {{ page.html|safe }}

{% endblock content %}

Flask-FlatPages 模块会默认从 pages 目录里寻找 .md 结尾的 Markdown 文档,所以我们把静态博客的内容都放在这个目录里:
$ vi app/pages/hello-world.md

title: Hello World

date: 2014-10-14

tags: [general, blog]
**Hello World**!
$ vi app/pages/test-flatpages.md

title: Test Flask FlatPages

date: 2014-10-15

tags: [python, flask]
Test [Flask-FlatPages](https://pythonhosted.org/Flask-FlatPages/)

运行

基本搞定,运行看看效果吧:

$ flask/bin/python app/blog.py

 * Running on http://127.0.0.1:8000/

 * Restarting with reloader

Flask入门教程实例:搭建一个静态博客

静态化

到目前为止,上面的博客运行良好,但是有个问题,这个博客还不是 “静态” 的,没有生成任何 html 文件,不能直接放到 nginx/apache 这样的 web 服务器下用。所以我们需要另一个 Flask 模块 Frozen-Flask 的帮助。

安装 Frozen-Flask:

$ flask/bin/pip install frozen-flask

修改 blog.py,导入 Flask-Frozen 模块,初始化 Freezer,使用 freezer.freeze() 生成静态 HTML:
$ vi app/blog.py

...

from flask_flatpages import FlatPages

from flask_frozen import Freezer

import sys

...

flatpages = FlatPages(app)

freezer = Freezer(app)

...

if __name__ == '__main__':

    if len(sys.argv) > 1 and sys.argv[1] == "build":

        freezer.freeze()

    else:

        app.run(port=8000)

运行 blog.py build 后就在 app 目录下生成 build 目录,build 目录里面就是我们要的 HTML 静态文件:
$ flask/bin/python app/blog.py build
$ ls app/

blog.py   build     pages     static    templates

更清晰的目录结构如下:
$ tree app

app

├── blog.py

├── build

│   ├── index.html

│   └── pages

│       ├── hello-world

│       │   └── index.html

│       └── test-flatpages

│           └── index.html

├── pages

│   ├── hello-world.md

│   └── test-flatpages.md

├── static

└── templates

    ├── base.html

    ├── index.html

    └── page.html
Python 相关文章推荐
Django框架中render_to_response()函数的使用方法
Jul 16 Python
Python中max函数用法实例分析
Jul 17 Python
python的dataframe和matrix的互换方法
Apr 11 Python
详解Python中的分组函数groupby和itertools)
Jul 11 Python
在Pycharm中自动添加时间日期作者等信息的方法
Jan 16 Python
Pytorch 抽取vgg各层并进行定制化处理的方法
Aug 20 Python
Python socket连接中的粘包、精确传输问题实例分析
Mar 24 Python
Python新手学习raise用法
Jun 03 Python
详解Django ORM引发的数据库N+1性能问题
Oct 12 Python
详解python中的三种命令行模块(sys.argv,argparse,click)
Dec 15 Python
python 离散点图画法的实现
Apr 01 Python
Python实现日志实时监测的示例详解
Apr 06 Python
Python中的高级数据结构详解
Mar 27 #Python
python中反射用法实例
Mar 27 #Python
Python中使用摄像头实现简单的延时摄影技术
Mar 27 #Python
python根据出生日期返回年龄的方法
Mar 26 #Python
python获取远程图片大小和尺寸的方法
Mar 26 #Python
python使用cStringIO实现临时内存文件访问的方法
Mar 26 #Python
python使用pil生成缩略图的方法
Mar 26 #Python
You might like
如何使用php绘制在图片上的正余弦曲线
2013/06/08 PHP
解决ThinkPHP关闭调试模式时报错的问题汇总
2015/04/22 PHP
php读取本地json文件的实例
2018/03/07 PHP
PHP格式化显示时间date()函数代码
2018/10/03 PHP
AJAX的跨域与JSONP(为文章自动添加短址的功能)
2010/01/17 Javascript
JavaScript学习笔记之获取当前目录的实现代码
2010/12/14 Javascript
JQuery扩展插件Validate 3通过参数设置错误信息
2011/09/05 Javascript
js判断undefined类型,undefined,null, 的区别详细解析
2013/12/16 Javascript
JS中的log对象获取以及debug的写法介绍
2014/03/03 Javascript
jQuery过滤选择器:not()方法使用介绍
2014/04/20 Javascript
jQuery取id有.的值的方法
2014/05/21 Javascript
提升PHP安全:8个必须修改的PHP默认配置
2014/11/17 Javascript
浅谈javascript中createElement事件
2014/12/05 Javascript
Bootstrap组件(一)之菜单
2016/05/11 Javascript
jQuery+Ajax+PHP弹出层异步登录效果(附源码下载)
2016/05/27 Javascript
js弹出框、对话框、提示框、弹窗实现方法总结(推荐)
2016/05/31 Javascript
浅谈JavaScript中的分支结构
2016/07/01 Javascript
Javascript OOP之面向对象
2016/07/31 Javascript
Bootstrap实现渐变顶部固定自适应导航栏
2020/08/27 Javascript
JavaScript实现图片无缝滚动效果
2017/07/07 Javascript
30分钟快速实现小程序语音识别功能
2018/11/27 Javascript
详解JavaScript对数组操作(添加/删除/截取/排序/倒序)
2019/04/28 Javascript
了解JavaScript中的选择器
2019/05/24 Javascript
layui checkbox默认选中,获取选中值,清空所有选中项的例子
2019/09/02 Javascript
使用 js 简单的实现 bind、call 、aplly代码实例
2019/09/07 Javascript
vue3修改link标签默认icon无效问题详解
2019/10/09 Javascript
python实现读取大文件并逐行写入另外一个文件
2018/04/19 Python
浅谈keras中Dropout在预测过程中是否仍要起作用
2020/07/09 Python
Tensorflow使用Anaconda、pycharm安装记录
2020/07/29 Python
CSS3 优势以及网页设计师如何使用CSS3技术
2009/07/29 HTML / CSS
毕业生求职信的经典写法
2014/01/31 职场文书
教师专业自荐书范文
2014/02/10 职场文书
内勤岗位职责
2015/02/10 职场文书
亲戚关系证明
2015/06/24 职场文书
大学生暑期实践报告
2015/07/13 职场文书
团队拓展训练感想
2015/08/07 职场文书