<Flask> Flask-FlatPages

Flask-FlatPagesを使ったマークダウン markdownで書いたテキストの表示。

https://pythonhosted.org/Flask-FlatPages/

この人のブログポストを実際にやってみた。

www.jamesharding.ca

まずは階層構造。

 % tree .
.
├── blog.py
├── content
│   └── posts
│       ├── aaa.md
│       └── bbb.md
├── templates
     ├── post.html
     └── posts.html

3 directories, 6 files

で、各コード。

blog.py

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

DEBUG = True
FLATPAGES_AUTO_RELOAD = DEBUG
FLATPAGES_EXTENSION = '.md'
FLATPAGES_MARKDOWN_EXTENSIONS = ['codehilite', 'extra']
FLATPAGES_ROOT = 'content'
POST_DIR = 'posts'

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


@app.route("/posts/")
def posts():
    posts = [p for p in flatpages if p.path.startswith(POST_DIR)]
    posts.sort(key=lambda item: item['date'], reverse=False)
    return render_template('posts.html', posts=posts)


@app.route('/posts/<name>/')
def post(name):
    path = '{}/{}'.format(POST_DIR, name)
    post = flatpages.get_or_404(path)
    return render_template('post.html', post=post)


@app.route('/pygments.css')
def pygments_css():
    return pygments_style_defs('default'), 200, {'Content-Type': 'text/css'}


if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] == "build":
        freezer.freeze()
    if len(sys.argv) > 1 and sys.argv[1] == "debug":
        pass
    else:
        app.run(debug=True)

templates/post.html

<link rel="stylesheet" href="{{ url_for('pygments_css') }}">
{{ post.html|safe }}
{{ post.title }}
{{ post.date }}

templates/posts.html

{% for post in posts %}
    <a href="{{ url_for('post', name=post.path.replace('posts/', '')) }}">
        {{ post.title }}
    </a>
    <small>{{ post.date }}</small>
    <br>
{% endfor %}

content/posts/bbb.md

title: bbb
date: 2016-05-06

# test

This is the test

````python
def aaa():
    print('aaa')
````

**end**

で、python blog.pyでランすると、content/posts/***.mdにストアされた、
マークダウン君たちのテキストが、html化されて表示される。
いいねー。

ちと、FlatPagesのオブジェクトを覗いてみた。

In [1]: run blog.py debug

In [2]: whos
Variable                        Type         Data/Info
------------------------------------------------------
DEBUG                           bool         True
FLATPAGES_AUTO_RELOAD           bool         True
FLATPAGES_EXTENSION             str          .md
FLATPAGES_MARKDOWN_EXTENSIONS   list         n=2
FLATPAGES_ROOT                  str          content
Flask                           type         <class 'flask.app.Flask'>
FlatPages                       type         <class 'flask_flatpages.flatpages.FlatPages'>
Freezer                         type         <class 'flask_frozen.Freezer'>
POST_DIR                        str          posts
app                             Flask        <Flask '__main__'>
flatpages                       FlatPages    <flask_flatpages.flatpage<...>ct at 0x000000000AFD1AC8>
freezer                         Freezer      <flask_frozen.Freezer obj<...>ct at 0x000000000BB3C128>
post                            function     <function post at 0x000000000BB3F620>
posts                           function     <function posts at 0x000000000BB3F598>
pygments_css                    function     <function pygments_css at 0x000000000BB3F6A8>
pygments_style_defs             function     <function pygments_style_<...>fs at 0x000000000BB2F158>
render_template                 function     <function render_template at 0x000000000BA3DE18>

flatpagesオブジェクトは、各ページのコレクション collection
なので、イタレートすると、各ページがでてくる。

In [4]: [p for p in flatpages]
Out[4]: [<Page 'posts/aaa'>, <Page 'posts/bbb'>]

各ページは、こんな感じ。

In [6]: dir([p for p in flatpages][0])
Out[6]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__gt__',
 '__hash__',
 '__html__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 '_meta',
 'body',
 'html',
 'html_renderer',
 'meta',
 'path']

In [7]: [p for p in flatpages][0].meta
Out[7]: {'date': datetime.date(2016, 5, 6), 'title': 'aaa'}

.metaがディクショナリで、各ページのテキストにyamlフォーマットで記述されたもの。

なるほど。

参考

nicolas.perriault.net

The Official YAML Web Site