Ibis

A template engine for people who enjoy the simpler things in life.

Version 3.3.0

Extensions


Custom Filters

A filter is simply a function that transforms and returns its first argument.

Custom filters are both extremely powerful and extremely easy to implement. They're registered using the @ibis.filters.register decorator.

Let's start with a simple example. Imagine we want a filter to round a floating-point number to 2 decimal places:

@ibis.filters.register("fmt_float")
def format_float(value):
    return "{:.2f}".format(value)

We can use our custom filter like this:

template = ibis.Template("{{ value|fmt_float }}")
assert template.render(value=123.456789) == "123.46"

More generally, our custom filter can take a format_string argument to format any kind of value:

@ibis.filters.register("fmt_value")
def format_value(value, format_string):
    return format_string.format(value)

We can use this custom filter like this:

template = ibis.Template("{{ value|fmt_value('{.2f}') }}")
assert template.render(value=123.456789) == "123.46"

Filter functions can take multiple arguments and support arguments with default values. As an example, we can register a filter to convert datetime objects into formatted strings:

@ibis.filters.register('dtformat')
def format_datetime(dt, format_string='%Y-%m-%d'):
    return dt.strftime(format_string)

This gives us a dtformat filter with an optional format_string argument that we can call on any datetime object, including the built-in now() function which returns a datetime object representing the current time:

{{ now()|dtformat }}

{{ now()|dtformat('%Y') }}

As it happens, dtformat already exists as a built-in filter. Re-registering the dtformat name would simply override the built-in filter with our own custom version.

Custom Instruction Tags

You can register custom instruction tags to supplement or override the built-in ones. Creating custom tags is more complicated than creating custom filters as you'll need to understand some of the internal details of how Ibis compiles template strings into trees of Node objects.

Every instruction tag corresponds to a subclass of the ibis.nodes.Node type. To create a new instruction tag, register a subclass using the @nodes.register decorator:

@ibis.nodes.register('foo')

You can give your new tag block scope by specifying an end word:

@ibis.nodes.register('foo', 'endfoo')

You'll need to turn to the source code itself for further details — see the ibis/nodes.py file for lots of examples to work from.

Custom Builtins

You can assign custom variables and functions to the ibis.context.builtins dictionary to make them available in all templates.

Custom Tag Syntax

You can customize Ibis's tag delimiter syntax to suit your own taste. The default tag delimiters are shown below:

ibis.compiler.comment_start = '{#'
ibis.compiler.comment_end = '#}'
ibis.compiler.print_start = '{{'
ibis.compiler.print_end = '}}'
ibis.compiler.eprint_start = '{$'
ibis.compiler.eprint_end = '$}'
ibis.compiler.instruction_start = '{%'
ibis.compiler.instruction_end = '%}'

All you need to do is assign new delimiter strings to the above variables.