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:
-
pelicanconf.pyneeded some work to tell Pelican to generate files namedindex.htmlinto directories named after their slugs. This is so posts will have nice URLs without the trailing.htmlARTICLE_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'
-
Set the
publishaction in theMakefileto$(PELICAN) $(INPUTDIR) -o $(PUBLISHDIR) -s $(PUBLISHCONF) $(PELICANOPTS)
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
PUBLISHDIRin the PelicanMakefile. I changed the default because I have a plan for the default. -
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> </form> ''' 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 theoutput/staticdirectory so that images and such would be served properly. -
And finally, installing vim-markdown make it much easier to edit markdown in vim.