{% include JB/setup %}html
翻译自:Dead easy yet powerful static website generator with Flaskpython
纯意译……如下是正文,和jekyll很像的感受,哈?34行代码完成一个静态站点生成器。web
我想将个人在线身份统合到一个单独的托管地方好久了,所以有了你如今浏览的这个网站。我也寻找一个静态网站架构有段时间了,尝试了许多但一个也不中意。这真使人沮丧。数据库
而后遇到Armin Ronacher的这个tweet:flask
<blockquote class="twitter-tweet tw-align-center"> <p>Frozen-Flask is really, really useful. Should have used that earlier.</p>— 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>浏览器
Armin是Flask这个Python微框架的做者,我喜欢flask的简洁。因此这个tweet一个机灵,我便开始探索Frozen-Flask的玩法。服务器
Frozen-Flask将Flask应用_冻结_成静态文件,这样你可以高速而无痛地部署它们。再佐以Flask-FlatPages,你得到了完美的生成静态站点工具集,这个站点将有因此你使用框架能获得的特性。markdown
在新文件夹中建立个新的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
:app
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)
见鬼,咱们刚刚作了什么?
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代码就完成了……不错吧?
固然,如今的版本弱爆了,你能一点一点的为它添加各类特性了。