New blog is new

Posterous is closing down, so I needed to find a new home for this blog. The idea of a statically-generated blog appealed to me and I wanted to run it on PythonAnywhere, so I started playing around with a couple of the Python static blog creators. Of the available ones Pelican and Nikola had the features that I wanted. I decided on Pelican because it could be configured to work better on PythonAnywhere.

Pelican has an import utility that can handle wordpress xml output and Posterous provided an export. The import didn't quite work, because the date formats were different. If I'd had more than a few posts, I would have scripted the format change, but a bit of hand-editing sorted everything out in a few minutes.

There are a couple of things that I did to get a setup that I liked on PythonAnywhere:

  1. needed some work to tell Pelican to generate files named index.html into directories named after their slugs. This is so posts will have nice URLs without the trailing .html

    ARTICLE_URL = '{date:%Y}/{date:%b}/{slug}'
    ARTICLE_SAVE_AS = '{date:%Y}/{date:%b}/{slug}/index.html'
    ARTICLE_LANG_URL = '{date:%Y}/{date:%b}/{slug}-{lang}'
    ARTICLE_LANG_SAVE_AS = '{date:%Y}/{date:%b}/{slug}-{lang}/index.html'
    PAGE_URL = 'pages/{slug}'
    PAGE_SAVE_AS = 'pages/{slug}/index.html'
    PAGE_LANG_URL = 'pages/{slug}-{lang}'
    PAGE_LANG_SAVE_AS = 'pages/{slug}-{lang}/index.html'
    AUTHOR_URL = 'author/{slug}'
    AUTHOR_SAVE_AS = 'author/{slug}/index.html'
    CATEGORY_URL = 'category/{slug}'
    CATEGORY_SAVE_AS = 'category/{slug}/index.html'
    TAG_URL = 'tag/{slug}'
    TAG_SAVE_AS = 'tag/{slug}/index.html'
    INDEX_SAVE_AS = 'index.html'
    TAGS_SAVE_AS = 'tags/index.html'
    CATEGORIES_SAVE_AS = 'categories/index.html'
    ARCHIVES_SAVE_AS = 'archives/index.html'
  2. Set the publish action in the Makefile to


    to separate the publishing directory from the general output directory and a web app and added a static file mapping with a blank URL and a dircectory that matches the PUBLISHDIR in the Pelican Makefile. I changed the default because I have a plan for the default.

  3. The plan mentioned in the previous point is to have a staging site that I can publish to without making it live. Another web app from a Flask quickstart and the following code does the trick. Just a word of warning: Although there's authentication involved, it's in no way secure. It's just a way of preventing robots from spidering it.

    import os
    from mimetypes import guess_type
    from flask import Flask, make_response, request, Response, session
    allowed_username = '<username>'
    app = Flask(__name__)
    app.debug = True
    BASE_PATH = '/home/glenn/blog_work/output'
    @app.route('/', methods=['GET', 'POST'])
    @app.route('/<path:file_path>', methods=['GET', 'POST'])
    def serve_static(file_path=''):
        if request.method == 'POST' and request.form['username'] == allowed_username:
            session['username'] = request.form['username']
        if not 'username' in session or session['username'] != allowed_username:
                return '''
                    <form action="" method="post">
                        <p><input type=text name=username>
                        <p><input type=submit value=Login>
        path = os.path.join(BASE_PATH, file_path)
        full_path = None
        if os.path.isfile(path):
            full_path = path
        if os.path.isdir(path):
            full_path = os.path.join(path, 'index.html')
        if full_path is not None:
            mimetype = guess_type(full_path)[0]
            return Response(open(full_path, 'r').read(), mimetype=mimetype)
        return make_response('not found', 404)
    # set the secret key.  keep this really secret:
    app.secret_key = '<a secret key>'

    This web app also needed a static file entry of /static/ to the output/static directory so that images and such would be served properly.

  4. And finally, installing vim-markdown make it much easier to edit markdown in vim.

comments powered by Disqus