Em's Site

Custom tag and category headings in Pelican

Table Of Contents

How to make custom tag and category pages in Pelican

This blog is was at one point made using Pelican. Pelican has pages that list all the blogs with a specific tag or category. The problem is there's only one HTML template for all the tags and categories, so there's limited customization possible. However, with a simple python function, it's possible to create custom headings for tag and category pages.

Since Pelican uses Jinja for templating, there's the ability to make custom Jinja filters. These are Python functions that return a string, which is output wherever the filter is called. The Python function needsto be in a Python file somewhere in the root folder. I created a filters/ folder to put it in, but you can place it anywhere, as long as it's accessible.

The data is put in a nested dictionary. A basic example is this:

custom_headings = {
        "tags": {
                "test": "testing",
        },
        "categories": {
                "testcategory": "testing2",
        },
}

where tags and categories will hold the custom headings for selected tags and categories. Here is the tag function:

def get_tag_heading(tag):
        if custom_text["tags"].get(tag.slug):
                return custom_text["tags"][tag.slug]
        else:
                return f"All {tag} blogs"

This function accepts a Pelican tag object. To make it easy, the key of the Python dictionary will be the slug of the tag. It uses the Python get() function to check if the slug is in the dict. If it is, the function returns the text from that key, otherwise it returns a generic heading.

The category function is the same as the tag function above, replace tag/tags with category/categories.

Next, Pelican needs to be aware of the filters. In pelicanconf.py, add from filters.custom_headings import get_category_heading, get_tag_heading at the top by the rest of the import statements.

To use this in a template, pass the tag or category object to the respective filter inside double brackets, like so:

<h1>{{ tag|get_tag_heading }}</h1>

and it will output either the string specified in the dictionary or the default string.