Plain is headed towards 1.0! Subscribe for development updates →

 1# Templates
 2
 3**Render HTML templates using Jinja.**
 4
 5- [Overview](#overview)
 6- [Template files](#template-files)
 7- [Extending Jinja](#extending-jinja)
 8- [Rendering templates manually](#rendering-templates-manually)
 9
10## Overview
11
12Plain uses Jinja2 for template rendering. You can refer to the [Jinja documentation](https://jinja.palletsprojects.com/en/stable/api/) for all of the features available.
13
14In general, templates are used in combination with `TemplateView` or a more specific subclass of it.
15
16```python
17from plain.views import TemplateView
18
19
20class ExampleView(TemplateView):
21    template_name = "example.html"
22
23    def get_template_context(self):
24        context = super().get_template_context()
25        context["message"] = "Hello, world!"
26        return context
27```
28
29```html
30<!-- example.html -->
31{% extends "base.html" %}
32
33{% block content %}
34    <h1>{{ message }}</h1>
35{% endblock %}
36```
37
38## Template files
39
40Template files can be located in either a root `app/templates`,
41or the `<pkg>/templates` directory of any installed package.
42
43All template directories are "merged" together, allowing you to override templates from other packages. The `app/templates` will take priority, followed by `INSTALLED_PACKAGES` in the order they are defined.
44
45## Extending Jinja
46
47Plain includes a set of default [global variables](./jinja/globals.py) and [filters](./jinja/filters.py). You can register additional extensions, globals, or filters either in a package or in your app. Typically this will be in `app/templates.py` or `<pkg>/templates.py`, which are automatically imported.
48
49```python
50# app/templates.py
51from plain.templates import register_template_filter, register_template_global, register_template_extension
52from plain.templates.jinja.extensions import InclusionTagExtension
53from plain.runtime import settings
54
55
56@register_template_filter
57def camel_case(value):
58    return value.replace("_", " ").title().replace(" ", "")
59
60
61@register_template_global
62def app_version():
63    return "1.0.0"
64
65
66@register_template_extension
67class HTMXJSExtension(InclusionTagExtension):
68    tags = {"htmx_js"}
69    template_name = "htmx/js.html"
70
71    def get_context(self, context, *args, **kwargs):
72        return {
73            "DEBUG": settings.DEBUG,
74            "extensions": kwargs.get("extensions", []),
75        }
76```
77
78## Rendering templates manually
79
80Templates can also be rendered manually using the [`Template` class](./core.py#Template).
81
82```python
83from plain.templates import Template
84
85comment_body = Template("comment.md").render({"message": "Hello, world!",})
86```