Posted: 16 March 2012
I want to be able to see "draft" posts rendered on my website without them being public.
So, I thought I should have a drafts.html page (perhaps protected by .htaccess, but at least not directly reachable from any public page). But, to populate that page, I'd need a list of draft posts. Currently 'post.py' just drops draft posts (and posts without permalinks?).
First step is to fix post.py
to return both the regular posts and the
draft posts. Second step is to fix run
in __init__.py
to cache the
drafts in the 'blog' object. Third step is to write the
drafts.html.mako
template to list the links to the draft blog entries.
And fourth step is to realize permapage.py doesn't write out draft posts,
and fix it to do so.
First, fix post.py
to return regular and draft posts:
--- a/_controllers/blog/post.py +++ b/_controllers/blog/post.py @@ -344,8 +344,10 @@ class Category(object): def parse_posts(directory): """Retrieve all the posts from the directory specified. - Returns a list of the posts sorted in reverse by date.""" + Returns two lists of the posts, regular and drafts, each sorted in reverse by date.""" posts = [] + drafts = [] + post_filename_re = re.compile( ".*((\.textile$)|(\.markdown$)|(\.org$)|(\.html$)|(\.txt$)|(\.rst$))") if not os.path.isdir("_posts"): @@ -372,7 +374,14 @@ def parse_posts(directory): logger.warning(u"{0} : Skipping this post.".format(e.value)) continue #Exclude some posts - if not (p.permalink is None or p.draft is True): - posts.append(p) + if p.permalink: + # For whatever reason, exclude all posts without permalinks + if p.draft: + drafts.append(p) + else: + posts.append(p) + posts.sort(key=operator.attrgetter('date'), reverse=True) - return posts + drafts.sort(key=operator.attrgetter('date'), reverse=True) + + return (posts, drafts)
Second, fix _controllers/blog/__init__.py
to accept the results from post.py
:
- blog.posts = post.parse_posts("_posts") + (blog.posts, blog.drafts) = post.parse_posts("_posts")
Third, write a simple drafts.html.mako
template:
<%inherit file="_templates/site.mako" /> <p> This is the private DRAFTs page. </p> <ul> % for post in bf.config.blog.drafts: <li><a href="${post.path}">${post.title}</a></li> % endfor </ul>
Fourth, fix permapage.py
to spit out draft pages, too. Plus I couldn't help refactoring it a bit.
--- a/_controllers/blog/permapage.py +++ b/_controllers/blog/permapage.py @@ -4,35 +4,44 @@ import re blog = bf.config.controllers.blog - def run(): write_permapages() def write_permapages(): "Write blog posts to their permalink locations" + site_re = re.compile(bf.config.site.url, re.IGNORECASE) - num_posts = len(blog.posts) + + materialize_collection(site_re, blog.posts) + materialize_collection(site_re, blog.drafts) - for i, post in enumerate(blog.posts): - if post.permalink: - path = site_re.sub("", post.permalink) - blog.logger.info(u"Writing permapage for post: {0}".format(path)) - else: - #Permalinks MUST be specified. No permalink, no page. - blog.logger.info(u"Post has no permalink: {0}".format(post.title)) - continue +def materialize_collection(site_re, blogs): + num_posts = len(blogs) + for i, post in enumerate(blogs): env = { "post": post, - "posts": blog.posts - } + "posts": blogs + } #Find the next and previous posts chronologically if i < num_posts - 1: - env['prev_post'] = blog.posts[i + 1] + env['prev_post'] = blogs[i + 1] if i > 0: - env['next_post'] = blog.posts[i - 1] + env['next_post'] = blogs[i - 1] - bf.writer.materialize_template( - "permapage.mako", bf.util.path_join(path, "index.html"), env) + materialize_post(site_re, i, post, env) + + +def materialize_post(site_re, i, post, env): + if not post.permalink: + #Permalinks MUST be specified. No permalink, no page. + blog.logger.info(u"Post has no permalink: {0}".format(post.title)) + return + + path = site_re.sub("", post.permalink) + blog.logger.info(u"Writing permapage for post: {0}".format(path)) + + bf.writer.materialize_template( + "permapage.mako", bf.util.path_join(path, "index.html"), env)