JP van Oosten

Custom Jinja2 filters when using bottle

Mar 24, 2013

I have been experimenting with Bottle lately. I have done a bit of Django development and I've always liked its template engine, especially the idea of template inheritance and the fact that it's not a layer on top of xml. So, when starting to experiment with Bottle, I wanted to use Jinja2 as that was inspired by the Django template engine.

One of the nice features of Jinja2 (and its inspiration) are filters. For example, in a template, one can use {{ name|capitalized }} which will output the value of name, but then capitalized. As this is merely for presentation, I think this actually belongs in the template.

You can even write your own filters, which are basically just python functions that are being called by the parser. However, I could not really find a clear explanation of how to automatically use my custom filters in the @view(templatename) decorator offered by bottle. Here is the solution I came up with:

from bottle import jinja2_view
view = functools.partial(jinja2_view,
    template_settings={'filters': filter_dict})

where filter_dict is a dictionary with a name to function mapping. functools.partial is a nice function (that is actually used in the bottle definition of jinja2_view as well), that allows you to wrap a function such that certain (keyword) arguments already filled in. In other words: the above code creates a new function that calls jinja2_view with the template_settings argument already filled in. Now, you don't have to pass template_settings each time you call view.

To automate adding filters to the filter_dict as much as possible, I wrote a simple @filter decorator:

filter_dict = {}
def filter(func):
    """Decorator to add the function to filter_dict"""
    filter_dict[func.__name__] = func
    return func

# Usage:
@filter
def quote(s):
    return urllib.quote(s)