Skip to main content

Adding filters to a Jinja2 template for Nikola

Adding filters to a Jinja2 template for Nikola

The Jinja2 template engine defines a suite of filters that can be used to transform text as it's rendered. You can define extra custom filters, and also make them available within Nikola templates (as long as the theme uses Jinja as its template engine, of course.)

I needed this to fix the import of data from an RSS feed using the continuous import plugin. Specifically I'm getting book reviews from Goodreads, where the timestamps of when I finished a book come down in a too-detailed format – for example including the time and timezone of the Goodreads server, not of me. To change this I need to take the timestamp from the RSS feed (as a string), turn it into a Python datetime object, and then generate a new string with less information.

There are two parts to this: defining the filter, and then installing it into Nikola. The definition is straightforward, just a Python function,and I included it directly into

  # Filters
  import datetime
  import dateparser

  def j2_dayonly_filter(d):
      '''Fix timestamps to only include the day on which something
      happened, and lose time and timezone information. This is needed
      to make Goodreads timestamps sensible.

      :param d: the timestamp, as a string
      :returns: the timestamp string with only its day-month-year components'''
      ts = dateparser.parse(d)
      return ts.strftime("%d %B %Y")

To make the filter available you don't use the Jinja2 environment registration mechanism, but instead include it into Nikola's TEMPLATE_FILTERS dict:

      "dayonly":  j2_dayonly_filter

The filter can then be used in a template, for example:

  {% if item.user_read_at %}
     Finished {{ item.user_read_at|dayonly }}.
  {% endif %}

which pipes the item.user_read_at field of the Goodreads RSS feed into the filter for display. If I define more filters I'll move them into their own file and then import that into, just for a clean decomposition.

Share this post to:


Comments powered by Disqus