Jinja2 is a templating language for Python that is very similar to Django’s templating system. It is very widely used and was the default templating system that came with Pelican. Coming from a Django background in templating and as a previous Mako templates user I was excited to try it out.
I won’t go into a full break down of differences between Django, Mako, and Jinja2. Quickly then, Mako is compiled into Python modules, essentially writing Python code in your templates. Django is a restrictive templating language built on the idea that you should be putting values, not logic, in your templates. Logic is handled through tags while variables can be transformed through the use of filters. Jinja2 builds off of Django supporting additional filters, tags, and functionality that gives it more power. With power comes responsibility, limit the logic in your templates.
During the transfer from my home-grown static file system I added a few Jinja2 filters to my Pelican configuration. I will expand on the plugins I added later on.
Suffixes for Dates
def suffix (d):
"""Returns a suffix for a given number."""
sfx = {
1: 'st',
2: 'nd',
3: 'rd'
}
return 'th' if 11 <= d <= 13 else sfx.get(d%10, 'th')
I wrote a short helper function because I wanted to be able to output 10th
and 1st
for dates. I’ve since avoided doing that but it’s helpful nontheless as Python’s built-in strftime
are limited.
Period Archive Titles
def archive_fmt (period):
"""Returns an archive formatted date."""
if len(period) == 1:
return period[0]
if len(period) == 2:
return u"{1} {0}".format(*period)
return u"{2} {3}{0}, {1}".format(suffix(period[2]), *period)
This enables me to title period archives as Archives for {{ period|archive_fmt }}
with minimal work in the template itself.
Post Years
def year_archives (dates):
"""Returns a list of years ordered descending from the given list of
dates."""
years = set()
for article in dates:
years.add(article.date.year)
for year in reversed(sorted(years)):
yield year
This powers the yearly period archives on the homepage.
Transforming Integers to Months
def int_to_month (m_int):
"""Turns an integer month into a long month."""
d = datetime(year=2014, day=1, month=m_int)
return d.strftime("%B")
Also used in the period archives to output a long month name.
Translation Support
def lang_to_en (value):
return {
"en": "English",
"zh": "中文",
"es": "Español",
"fr": "Français"
}.get(value, "NO LANGUAGE")
This is a quick helper for when an article has translations. This means each translation link can be represented as the language (中文) instead of the two character language code (zh).
Adding custom filters and extensions to Jinja2 in Pelican is as simple as defining a function and adding it to the JINJA_FILTERS
map in your settings.