Plain is headed towards 1.0! Subscribe for development updates →

 1# Templates
 2
 3**Render HTML templates using Jinja.**
 4
 5Plain 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.
 6
 7In general, templates are used in combination with `TemplateView` or a more specific subclass of it.
 8
 9```python
10from plain.views import TemplateView
11
12
13class ExampleView(TemplateView):
14    template_name = "example.html"
15
16    def get_template_context(self):
17        context = super().get_template_context()
18        context["message"] = "Hello, world!"
19        return context
20```
21
22```html
23<!-- example.html -->
24{% extends "base.html" %}
25
26{% block content %}
27    <h1>{{ message }}</h1>
28{% endblock %}
29```
30
31## Template files
32
33Template files can be located in either a root `app/templates`,
34or the `<pkg>/templates` directory of any installed package.
35
36All 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.
37
38## Extending Jinja
39
40Plain 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.
41
42```python
43# app/templates.py
44from plain.templates import register_template_filter, register_template_global, register_template_extension
45from plain.templates.jinja.extensions import InclusionTagExtension
46from plain.runtime import settings
47
48
49@register_template_filter
50def camel_case(value):
51    return value.replace("_", " ").title().replace(" ", "")
52
53
54@register_template_global
55def app_version():
56    return "1.0.0"
57
58
59@register_template_extension
60class HTMXJSExtension(InclusionTagExtension):
61    tags = {"htmx_js"}
62    template_name = "htmx/js.html"
63
64    def get_context(self, context, *args, **kwargs):
65        return {
66            "csrf_token": context["csrf_token"],
67            "DEBUG": settings.DEBUG,
68            "extensions": kwargs.get("extensions", []),
69        }
70```
71
72## Rendering templates manually
73
74Templates can also be rendered manually using the [`Template` class](core.py#Template).
75
76```python
77from plain.templates import Template
78
79comment_body = Template("comment.md").render({"message": "Hello, world!",})
80```