Templates

coltrane comes with two minimal templates that get used by default: coltrane/base.html and coltrane/content.html. Overriding those templates work just like in Django.

Override included templates

coltrane/base.html

Create a file named templates/coltrane/base.html in your app to override the base template. By default, it needs to include a content block.

{% block content %}{% endblock content %}

coltrane/content.html

Create a file named templates/coltrane/content.html in your app to override the content template. By default, it needs to include a content block for the base template and {{ content }} to render the markdown.

Note

The content template variable is already “marked safe” so you do not need to use a safe filter.

{% block content %}{{ content }}{% endblock content %}

Custom template

Specify a custom template with a template variable in the markdown frontmatter.

content/index.md

---
title: This is good content
template: sample_app/new-template.html
---

# Heading 1

This will use sample_app/new-template.html to render content.

sample_app/new-template.html

<title>{{ title }}</title>

{{ content }}

Generated index.html

<title>This is good content</title>

<h1 id="heading-1">Heading 1</h1>

<p>This will use sample_app/new-template.html to render content.</p>

Template tags

Template tags are the way for Django templates to use Python code. Django has a large list of built-in template tags for everything from looping over objects, date formatting, boolean logic with if/else blocks, or getting the length of an object. By default, all template tags in Django are available in markdown content files.

Coltrane template tags

directory_contents

A list of the content at a particular directory.

List markdown files based on the request path

If the request url is https://localhost:8000/ and there are these files:

  • content/test1.md

  • content/test2.md

# Contents

{% directory_contents as directory_contents %}

{% for content in directory_contents %}

- {{ content.slug }}

{% endfor %}
<h1 id="contents">Contents</h1>

<ul>
  <li>test1</li>
  <li>test2</li>
</ul>

List markdown files based on a particular directory

If the request url is https://localhost:8000/ and there are these files:

  • content/articles/article1.md

  • content/articles/article2.md

# Articles

{% directory_contents "articles" as directory_contents %}

{% for content in directory_contents %}

- {{ content.slug }}

{% endfor %}
<h1 id="articles">Articles</h1>

<ul>
  <li>article1</li>
  <li>article2</li>
</ul>

Exclude a slug from being included

If the request url is https://localhost:8000/ and there are these files:

  • content/articles/article1.md

  • content/articles/article2.md

# Articles

{% directory_contents "articles" exclude="article1" as directory_contents %}

{% for content in directory_contents %}

- {{ content.slug }}

{% endfor %}
<h1 id="articles">Articles</h1>

<ul>
  <li>article2</li>
</ul>

Sort the results of the directory

The order_by kwarg will sort the results by a particular key. Available keys are slug, now, and anything in the YAML frontmatter. All keys will be coerced to strings and if a key is missing an empty string will be used by default.

If the request url is https://localhost:8000/ and these files are present in the content directory:

  • content/article1.md

  • content/article2.md

# Sorted Articles

{% directory_contents order_by="slug" as directory_contents %}

{% for content in directory_contents %}

- {{ content.slug }}

{% endfor %}
<h1 id="sorted-articles">Sorted Articles</h1>

<ul>
  <li>article1</li>
  <li>article2</li>
</ul>
# Reverse Sorted Articles

{% directory_contents order_by="-slug" as directory_contents %}

{% for content in directory_contents %}

- {{ content.slug }}

{% endfor %}
<h1 id="reverse-sorted-articles">Reverse Sorted Articles</h1>

<ul>
  <li>article2</li>
  <li>article1</li>
</ul>

include_md

Similar to the include template tag, but can be used to include a markdown file and have it render correctly into HTML. It can be used in markdown files or in HTML templates.

# include_md

{% include_md '_partial.md' %}
<h1>include_md</h1>

{% include_md '_partial.md' %}

parent

A filter that returns the parent directory for a particular path. Can be passed a request or a string.

<!-- request of http://localhost/articles/some-article -->
{{ request|parent }} == '/articles'
{{ 'http://localhost/articles/some-article'|parent|parent }} == ''

to_html

Convert raw markdown text to html. This is probably the most useful in integrated mode.

views.py

def my_view(request):
    markdown_text = """---
title: Article 1
---

# {{ title }}
"""
    ...

my_template.html

<main>
    {{ markdown_text|to_html }}
</main>

Rendered html content

<main>
   <h1>Article 1</h1>
</main>

Humanize template tags

django.contrib.humanize includes a useful template tags to format numbers and dates in human-friendly ways. Normally it needs to be enabled and loaded in templates manually, but coltrane enables it by default so it is available to use in markdown content files automatically.

Custom template tags

coltrane will automatically include any custom template tags it finds in the templatetags directory to be used in markdown content files.

templatetags/custom_tags.py

from django import template

register = template.Library()

@register.filter(name="test")
def test(value, arg):
    return value + " is a test"

content/index.md

{{ "This"|test }}

Generated index.html

This is a test