HTML Templating

What is templating?

If you're building any sort of website, you likely don't want to write HTML from Python strings. Instead, you would rather just render HTML files and keep your Python code seperate.

However, this has a drawback: you can't put variables into your HTML. Nearly all Python web frameworks use templating as a solution.

Templating is the use of a template engine to put Python code in your HTML. For a more in-depth explanation, see the Python Wiki.

Templating API

In View, the main template API entry point is the template function. Because this function performs I/O, it is asynchronous.

The only required argument to template is the name or path of the template to be used. For example:

from view import new_app, template

app = new_app()

@app.get("/")
async def index():
    return await template("index")  # this refers to index.html

@app.get("/other")
async def other():
    return await template("index.html")  # works the same way

app.run()

The most notable difference about view.py's templating API is that parameters are automatically included from your scope (i.e. you don't have to pass them into the call to template). If you're against this behavior, you may disable it in the configuration via the globals and locals settings.

view.templates.template(name: str | Path, directory: str | Path | None = _ConfigSpecified, engine: TemplateEngine | None = _ConfigSpecified, frame: Frame | None | _CurrentFrameType = _CurrentFrame, app: App | None = None, **parameters: Any) -> HTML async

Render a template with the specified engine. This returns a view.py HTML response.

You can override the template engine and settings via the engine and directory parameters. For example, if the engine was view, the below would use mako:

from view import new_app, template

app = new_app()

@app.get('/')
async def index():
    return await template("index", engine="mako")

app.run()

There's also a direct variation of template on App.

from view import new_app

app = new_app()

@app.get("/")
async def index():
    return await app.template("index")

app.run()

The following template engines are supported:

The View Engine

View has it's own built in template engine that is used by default. It's based around the usage of a <view> tag, which is more limited, yet pretty to look at.

A <view> element can have any of the following attributes:

Examples

ref can be used to take variables, but may also be used to display any Python expression. For example, if you had defined hello = "world":

<p>Hello, <view ref="hello" /></p>
<p>The length of hello is <view ref="len(hello)" /></p>

If you had declared my_list = [1, 2, 3], you could iterate through it like so:

<view iter="my_list" item="i">
    <view ref="i" />
</view>
The above would result in 123

if, elif, and else are only shown if their cases are met. So, for example:

<view if="user.type == 'admin'">
    <view template="admin_panel" />
</view>
<view elif="user.type == 'moderator'">
    <view template="mod_panel" />
</view>
<view else>
    <p>You must be an admin to use the admin panel!</p>
</view>

Using Other Engines

If you would like to use an unsupported engine (or use extra features of a supported engine), you can do one of two things:

For example, if you wanted to customize Jinja, you shouldn't use View's template, but instead just use it manually:

from view import new_app
from jinja2 import Environment

app = new_app()
env = Environment()

@app.get('/')
async def index():
    return env.get_template("mytemplate.html").render()

app.run()

Review

Template engines are used to mix your Python code and HTML. You can use View's template or (App.template, if the App is available already) function to render a template with one of the supported engines, which are:

If you would like to use an unsupported engine, you can make a feature request on GitHub, or use it's API manually.