文档章节

Flask驱动的静态站点生成器(译)

yyliu
 yyliu
发布于 2012/11/19 21:38
字数 1713
阅读 2885
收藏 6

{% include JB/setup %}

翻译自:Dead easy yet powerful static website generator with Flask

纯意译……以下是正文,和jekyll很像的感觉,哈?34行代码完成一个静态站点生成器。


我想将我的在线身份统合到一个单独的托管地方很久了,因此有了你现在浏览的这个网站。我也寻找一个静态网站架构有段时间了,尝试了许多但一个也不中意。这真令人沮丧。

然后遇到Armin Ronacher的这个tweet

<blockquote class="twitter-tweet tw-align-center"> <p>Frozen-Flask is really, really useful. Should have used that earlier.</p>&mdash; Armin Ronacher (@mitsuhiko) <a href="https://twitter.com/mitsuhiko/status/166570613295689728" data-datetime="2012-02-06T17:15:03+00:00">February 6, 2012</a> </blockquote>

ArminFlask这个Python微框架的作者,我喜欢flask的简洁。所以这个tweet一个机灵,我便开始探索Frozen-Flask的玩法。

Frozen-Flask将Flask应用_冻结_成静态文件,这样你能够高速而无痛地部署它们。再佐以Flask-FlatPages,你获得了完美的生成静态站点工具集,这个站点将有所以你使用框架能得到的特性。

  • 酷的urls和简单的路径管理
  • 强大的模板
  • 本地动态服务
  • 静态版本管理

第一轮:项目搭建

在新文件夹中创建个新的virtualenv,使用pip安装必要的包:

$ mkdir sample_project && cd !$
$ mkvirtualenv --no-site-packages `pwd`/env
$ source env/bin/activate
$ pip install Flask Frozen-Flask Flask-FlatPages

写我们第一个版本的sitebuilder.py

from flask import Flask
app = Flask(__name__)

@app.route("/")
def index():
    return "Hello World!"

if __name__ == "__main__":
    app.run(port=8000)

运行它;你应该看到类似:

$ python sitebuilder.py 
 * Running on http://127.0.0.1:8000/ 
 * Restarting with reloader

用浏览器打开_http://:127.0.0.1:8000_看是否正常。

又一轮:添加纯文本页面

Flask-FlatPages为你的Flask应用提供一套页面。相对动态页面从关系数据库构建,静态页面是从纯文本文件构建。

在你的项目跟文件夹下创建一个pages/目录,新建一个hello-wolrd.md扔进去:

$ mkdir pages $ vi pages/hello-world.md

hello-world.md文件:

title: Hello World
date: 2012-03-04

**Hello World**, from a *page*!

如你所见你可以在页面内容中写入Markdown。所以让我们重新写我们的应用来为通过文件名为任何纯文本提供服务。

from flask import Flask
from flask_flatpages import FlatPages

DEBUG = True
FLATPAGES_AUTO_RELOAD = DEBUG
FLATPAGES_EXTENSION = '.md'

app = Flask(__name__)
app.config.from_object(__name__)
pages = FlatPages(app)

@app.route('/')
def index():
    return "Hello World"

@app.route('/<path:path>/')
def page(path):
    return pages.get_or_404(path).html

if __name__ == '__main__':
    app.run(port=8000)

现在访问http://127.0.0.1:8000/hello-world/将呈现渲染后的纯文本。注意通过page对象获得html属性markdown源码被转换成html。

又一轮:添加模板

flask使用jinja2模板引擎,让我们创建一些模板来装饰页面。首先在项目根目录下创建一个templates文件夹:

$ mkdir templates

templates/base.html中创建基本布局:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>My site</title>
</head>
<body>
    <h1><a href="{{ url_for("index") }}">My site</a></h1>
{% block content %}
    <p>Default content to be displayed</p>
{% endblock content %}
</body>
</html>

注意url_for()这个模板函数,这是我们使用Flask和Jinjia2生成url的方式。

现在用page.html模板来填充页面内容的布局:

{% extends "base.html" %}

{% block content %}
    <h2>{{ page.title }}</h2>
    {{ page.html|safe }}
{% endblock content %}

我们的应用现在应该是:

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__)
pages = FlatPages(app)

@app.route('/')
def index():
    return "Hello World"

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

if __name__ == '__main__':
    app.run(port=8000)

见鬼,我们刚刚做了什么?

  • 创建了一个应用的模板;一个通用布局(base.html)和一个页面模板(page.html)
  • 我们使用render_template函数对页面用页面模板装饰。
  • 页面模板扩展基本模板来避免在每个页面都复制粘帖相同的内容。

又一轮:在主页呈现页面列表

现在我们的主页弱爆了。我们让它列出所有存在的页面。

创建一个templates/index.html

{% extends "base.html" %}

{% block content %}
    <h2>List of stuff</h2>
    <ul>
    {% for page in pages %}
        <li>
            <a href="{{ url_for("page", path=page.path) }}">{{ page.title }}</a>
        </li>
    {% else %}
        <li>No stuff.</li>
    {% endfor %}
    </ul>
{% endblock content %}

随意地创建更多纯文本页面,就像我们创建hello-world.md一样,将文件保存在pages/目录下,使用.md扩展名。

我们应用中的index()路径现在应该这样:

重载主页,页面列表将呈现。真他×简单。

又一轮:给页面添加元数据

Flask-FlatPages允许像我们创建和hello-world.md的标题和日期一样添加元数据,并且通过page.meta来存取它们,获得看上去蠢蠢的python字典。真令人吃惊,不是吗?

让我们假设想要给页面添加标签,我们的hello-world.md将变成:

title: Hello World
date: 2012-03-04
tags: [general, awesome, stuff]

**Hello World**, from a *page*!

元数据用YAML描述,因此你能够使用字符串、布尔、整数、浮点、列表、甚至字典,它们将转换成Python相应的内在等价物。

我们将使用两个包含共享部分的不同的模板来列出普通页面和标签页面,index.html现在应该是:

{% extends "base.html" %}

{% block content %}
    <h2>List of stuff</h2>
    {% with pages=pages  %}
        {% include "_list.html" %}
    {% endwith %}
{% endblock content %}

创建tag.html模板,它将用来呈现标签页面列表:

{% extends "base.html" %}

{% block content %}
    <h2>List of stuff tagged <em>{{ tag }}</em></h2>
    {% with pages=pages  %}
        {% include "_list.html" %}
    {% endwith %}
{% endblock content %}

新建的_list.html模板应该包含:

<ul>
{% for page in pages %}
    <li>
        <a href="{{ url_for("page", path=page.path) }}">{{ page.title }}</a>
    {% if page.meta.tags|length %}
        | Tagged:
        {% for page_tag in page.meta.tags %}
            <a href="{{ url_for("tag", tag=page_tag) }}">{{ page_tag }}</a>
        {% endfor %}
    {% endif %}
    </li>
{% else %}
    <li>No page.</li>
{% endfor %}
</ul>

向应用中添加新的tag路径,使用新的tag.html模板:

@app.route('/tag/<string:tag>/')
def tag(tag):
    tagged = [p for p in pages if tag in p.meta.get('tags', [])]
    return render_template('tag.html', pages=tagged, tag=tag)

注:若你之前不喜欢python的列表推导式,现在你会了。

又一轮:生成静态页面

好的,现在我们只要有一个动态网站,为存储在文件系统上的纯文本页面提供服务:废话。但是我们当然不是Flask应用而是一堆静态文件,省去了任何应用服务器。

来进入Frozen-Flask。它的使用真××简单:

import sys

from flask import Flask, render_template
from flask_flatpages import FlatPages
from flask_frozen import Freezer

DEBUG = True
FLATPAGES_AUTO_RELOAD = DEBUG
FLATPAGES_EXTENSION = '.md'

app = Flask(__name__)
app.config.from_object(__name__)
pages = FlatPages(app)
freezer = Freezer(app)

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

@app.route('/tag/<string:tag>/')
def tag(tag):
    tagged = [p for p in pages if tag in p.meta.get('tags', [])]
    return render_template('tag.html', pages=tagged, tag=tag)

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

if __name__ == '__main__':
    if len(sys.argv) > 1 and sys.argv[1] == "build":
        freezer.freeze()
    else:
        app.run(port=8000)

然后运行:

$ python sitebuilder.py build

打开构建文件夹键入如下命令:

$ tree
.
├── hello-world
│   └── index.html
├── index.html
└── tag
    ├── awesome
    │   └── index.html
    ├── general
    │   └── index.html
    └── stuff
        └── index.html

5 directories, 5 files

想法:吓坏了

你现在能部署build目录下的任何文件到任何能托管静态文件的地方了,而你仅仅用34行Python代码就完成了……不错吧?

当然,现在的版本弱爆了,你能一点一点的为它添加各种特性了。

© 著作权归作者所有

共有 人打赏支持
yyliu
粉丝 31
博文 14
码字总数 20045
作品 0
无锡
私信 提问
【译】用Go实现一个静态博客生成器

【译】用Go实现一个静态博客生成器 Go语言学习园地博客2017-06-2028 阅读 go生成器 静态站点生成器是一种工具,给一些输入(例如,markdown),使用HTML,CSS和JavaScript生成完全静态的网站...

Go语言学习园地博客
2017/06/20
0
0
静态网站生成器--Hyde

使用hyde可以快速构建一个轻量级静态网站。Hyper的文档正在开发,不过仍有一些很好的教程可以参考,比如merlinrebrovic写的Hyde starter kit,如果你喜欢Twitter的bootstrap框架,可以尝试a...

匿名
2017/03/07
173
0
GitLab 8.17 发布,社区版也支持 GitLab Pages 了

GitLab 8.17 发布了,GitLab 8.17 与 GitLab Pages 一起在 GitLab CE 和 Squash on Merge 上发布。 静态站点的出现允许组织不再担心必须保护,更新和维护底层 CMS。静态网站速度快,而且功能...

局长
2017/02/24
3.9K
17
Jekyll v3.7.4 发布,简单易用的静态站点生成器

Jekyll 是一个简单的博客形态的静态站点生成器,适用于个人、项目或组织站点。可以想像它是一个基于文件的 CMS ,没有任何复杂性。 Jekyll 收集你的内容,呈现 Markdown 和 Liquid 模板,并生...

王练
2018/09/09
501
1
Jekyll v3.8.2 发布,简单易用的静态站点生成器

Jekyll 是一个简单的博客形态的静态站点生成器,适用于个人、项目或组织站点。可以想像它是一个基于文件的 CMS ,没有任何复杂性。 Jekyll 收集你的内容,呈现 Markdown 和 Liquid 模板,并生...

王练
2018/05/20
289
0

没有更多内容

加载失败,请刷新页面

加载更多

微信退款异步通知解密异常->填充无效,无法被移除

该问题是怎么引起的? AESDecrypt 加密处理发生异常 重现步骤 使用模拟工具 POSTMan 发送模拟通知 示例报文一: <return_code>SUCCESS</return_code><mch_id></mch_id><nonce_str></nonce_st......

夏至如沫
20分钟前
1
0
PC端网页使用微信扫码获取用户精确地理位置的一种解决方案[未测试]

移动互联网时代,获取用户地理位置来实现LBS当然不再话下。 在传统的PC浏览器应用领域,想获取用户的位置信息一般采用第三方的IP库,比如:淘宝IP地址库。但这种解决方案的缺陷是显而易见的:...

dragon_tech
22分钟前
1
0
【机器学习PAI实战】—— 玩转人工智能之利用GAN自动生成二次元头像

前言 深度学习作为人工智能的重要手段,迎来了爆发,在NLP、CV、物联网、无人机等多个领域都发挥了非常重要的作用。最近几年,各种深度学习算法层出不穷, Generative Adverarial Network(GAN...

迷你芊宝宝
25分钟前
1
0
Dijkstra算法之 Java详解

迪杰斯特拉算法介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为...

孟飞阳
28分钟前
1
0
php7.2安装zookeeper扩展

简单记录下安装过程。 一、安装libzookeeper cd /usr/local/src/wget http://mirror.bit.edu.cn/apache//zookeeper/zookeeper-3.4.5/zookeeper-3.4.5.tar.gztar -xf zookeeper-3.4.5.ta......

叫我哀木涕
37分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部