{% 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代碼就完成了……不錯吧?
固然,如今的版本弱爆了,你能一點一點的爲它添加各類特性了。