Random Ramblings
Mako doesn't like what I'm doing
February 06, 2012 at 10:00 AM | categories: website, hacking aroundI'm working on my website again, and to try and fix categories being listed several times in the navigation bar instead of once, I seem to have introduced another.
I'd managed to have each category from each post printed out (See code below), but there was a problem: categories with multiple posts were being listed multiple times.
% for post in bf.config.blog.posts[:]:
% for category in post.categories:
<li><a href="category/${category}">${category}</a></li>
% endfor
% endfor
What I needed was a way to have python/mako check for duplicates and only print out values once. I asked andrew for some help, and he suggested I use this:
buffer = [ '<li><a href="category/%s">%s</a></li>' % (category, category) for post in bf.config.blog.posts for category in post.categories ]
And it looks pretty cool. I stuck a % in front of it (like the for loops had), and it exploded:
16:36:10 kgoetz@epicfail: ~/srccache/website-blogofile $ SKIPRST='x' ./_make.sh
+ blogofile build
WARNING:blogofile.post:2011102301-running_crg_derbyscoreboard_behind_apache.rst: Post has no YAML section : Skipping this post.
ERROR:blogofile.writer:Error rendering template
Traceback (most recent call last):
File "/usr/lib/pymodules/python2.6/blogofile/writer.py", line 155, in template_render
return template.render(**attrs)
File "/usr/lib/pymodules/python2.6/mako/template.py", line 189, in render
return runtime._render(self, self.callable_, args, data)
[...cut lots of mako calls...]
File "/usr/lib/pymodules/python2.6/mako/parsetree.py", line 69, in __init__
code = ast.PythonFragment(text, **self.exception_kwargs)
File "/usr/lib/pymodules/python2.6/mako/ast.py", line 74, in __init__
code, **exception_kwargs)
CompileException: Fragment 'buffer = [ '<li><a href="category/%s">%s</a></li>' % (category, category) for post in bf.config.blog.posts for category in post.categories ]' is not a partial control statement in file '_templates/navigation.mako' at line: 12 char: 1
After reading the docs it turns out that % is used for things like if/else/for/while etc. What I needed for my python line (buffer= []) was %%.
The code snippet is now:
<%
buffer = [ '<li><a href="category/%s">%s</a></li>' % (category, category) for post in bf.config.blog.posts for category in post.categories ]
%>
Thanks to Andrew for the buffer line, its much fancier then what I had.
Removing duplicate categories.
The problem with the code above is that it collects duplicates into buffer. This means printing it directly through mako lists the tags several times in the side bar - not a feature.
An easy solution is available thanks to Nathan Hamiel of neohaxor.org, in one line of python. (See the next section for the line, albeit combined with the initial code).
The result
The final template file looks like this:
<%
# Build an array with all the categories in it.
# Lowercase so we don't have (eg) Debian and debian listed.
all_categories = [ '<li><a href="/category/%s">%s</a></li>' % \
(repr(category).lower(), repr(category).lower()) \
for post in bf.config.blog.posts for category in post.categories ]
# Dedupe the array before adding it to the nav bar.
nodupes_categories = set(all_categories)
%>
<ul>
% for category in nodupes_categories:
${category}
% endfor
</ul>