Tornado is a Python web framework and asynchronous networking library designed for applications requiring long-lived connections to many users.
Server-side template engine with automatic escaping, inheritance, and integration with the web framework. Supports both file-based and in-memory templates.
Template compilation and rendering with support for template inheritance, automatic escaping, and custom filters.
class Template:
"""Compiled template object."""
def __init__(self, template_string: str, name: str = "<string>", loader=None, compress_whitespace: bool = None, autoescape: str = "xhtml_escape", whitespace: str = None):
"""
Initialize template.
Args:
template_string: Template source code
name: Template name for error reporting
loader: Template loader instance
compress_whitespace: Whether to compress whitespace
autoescape: Autoescape function name
whitespace: Whitespace handling mode
"""
def generate(self, **kwargs) -> bytes:
"""
Generate template output.
Args:
**kwargs: Template variables
Returns:
Rendered template as bytes
"""
@property
def code(self) -> str:
"""Get generated Python code."""
@property
def name(self) -> str:
"""Get template name."""Template loaders for loading templates from various sources including filesystem and dictionaries.
class BaseLoader:
"""Base template loader interface."""
def __init__(self, autoescape: str = "xhtml_escape", namespace=None, whitespace: str = None):
"""
Initialize loader.
Args:
autoescape: Default autoescape function
namespace: Template namespace dict
whitespace: Whitespace handling mode
"""
def reset(self):
"""Clear template cache."""
def resolve_path(self, name: str, parent_path: str = None) -> str:
"""
Resolve template path.
Args:
name: Template name
parent_path: Parent template path
Returns:
Resolved template path
"""
def load(self, name: str, parent_path: str = None) -> Template:
"""
Load template by name.
Args:
name: Template name
parent_path: Parent template path
Returns:
Compiled Template object
"""
class Loader(BaseLoader):
"""Template loader for filesystem templates."""
def __init__(self, root_directory: str, **kwargs):
"""
Initialize filesystem loader.
Args:
root_directory: Root directory for templates
**kwargs: Additional loader options
"""
def get_modified_time(self, name: str) -> float:
"""Get template modification time."""
def load(self, name: str, parent_path: str = None) -> Template:
"""Load template from filesystem."""
class DictLoader(BaseLoader):
"""Template loader for in-memory templates."""
def __init__(self, dict: Dict[str, str], **kwargs):
"""
Initialize dictionary loader.
Args:
dict: Dictionary mapping template names to source code
**kwargs: Additional loader options
"""
def load(self, name: str, parent_path: str = None) -> Template:
"""Load template from dictionary."""Built-in template filters and utilities for template processing.
def filter_whitespace(mode: str, text: str) -> str:
"""
Filter whitespace in template.
Args:
mode: Whitespace mode ("single", "oneline", "all")
text: Template text
Returns:
Filtered text
"""
# Built-in template functions (available in templates)
def xhtml_escape(value) -> str:
"""Escape value for HTML/XML output."""
def url_escape(value: str, plus: bool = True) -> str:
"""URL-encode value."""
def json_encode(value) -> str:
"""JSON-encode value."""
def squeeze(value: str) -> str:
"""Replace multiple whitespace with single space."""
def linkify(text: str, shorten: bool = False, extra_params: str = "", require_protocol: bool = False, permitted_protocols: List[str] = None) -> str:
"""
Convert URLs in text to HTML links.
Args:
text: Text to process
shorten: Whether to shorten long URLs
extra_params: Extra link parameters
require_protocol: Whether to require protocol in URLs
permitted_protocols: List of allowed protocols
Returns:
Text with HTML links
"""Templates use Python-like syntax with special delimiters:
{{ expression }} - Expression output{% statement %} - Control statements{# comment #} - Comments<!-- Variable output -->
<h1>{{ title }}</h1>
<p>{{ user.name }}</p>
<!-- Expressions -->
<p>{{ "Hello " + user.name }}</p>
<p>{{ items|length }}</p>
<p>{{ price * 1.1 }}</p><!-- Conditionals -->
{% if user %}
<p>Hello, {{ user.name }}!</p>
{% else %}
<p>Please log in.</p>
{% end %}
<!-- Loops -->
{% for item in items %}
<li>{{ item.name }} - ${{ item.price }}</li>
{% end %}
<!-- Try/except -->
{% try %}
<p>{{ risky_operation() }}</p>
{% except %}
<p>Operation failed</p>
{% end %}<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Default Title{% end %}</title>
</head>
<body>
<div id="content">
{% block content %}{% end %}
</div>
</body>
</html>
<!-- child.html -->
{% extends "base.html" %}
{% block title %}Page Title{% end %}
{% block content %}
<h1>Page Content</h1>
<p>This is the page content.</p>
{% end %}<!-- Include other templates -->
{% include "header.html" %}
<main>
Content here
</main>
{% include "footer.html" %}<!-- Built-in filters -->
<p>{{ text|escape }}</p>
<p>{{ url|url_escape }}</p>
<p>{{ data|json_encode }}</p>
<p>{{ content|linkify }}</p>
<!-- Custom filters (defined in loader namespace) -->
<p>{{ date|dateformat("%Y-%m-%d") }}</p>import tornado.template
# Create template from string
template = tornado.template.Template("""
<html>
<head><title>{{ title }}</title></head>
<body>
<h1>{{ title }}</h1>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% end %}
</ul>
</body>
</html>
""")
# Render template
output = template.generate(
title="My Page",
items=["Item 1", "Item 2", "Item 3"]
)
print(output.decode('utf-8'))import tornado.template
import tornado.web
# Create template loader
loader = tornado.template.Loader("templates")
class MainHandler(tornado.web.RequestHandler):
def get(self):
# Render template file
self.render("index.html",
title="Welcome",
user={"name": "John Doe"})
# Application with template path
app = tornado.web.Application([
(r"/", MainHandler),
], template_path="templates")import tornado.template
import datetime
def format_date(date):
return date.strftime("%B %d, %Y")
# Custom namespace with functions
namespace = {
'format_date': format_date,
'current_year': datetime.datetime.now().year
}
loader = tornado.template.Loader("templates", namespace=namespace)
# Now templates can use {{ format_date(post.date) }}import tornado.template
# Template with HTML escaping (default)
template = tornado.template.Template("""
<p>{{ user_input }}</p>
<p>{% raw user_input %}</p> <!-- Raw output, no escaping -->
""", autoescape="xhtml_escape")
# Render with user input
output = template.generate(user_input="<script>alert('xss')</script>")# Template namespace type
TemplateNamespace = Dict[str, Any]
# Template source type
TemplateSource = str
# Template name type
TemplateName = str
# Whitespace mode type
WhitespaceMode = str # "single", "oneline", "all"
# Autoescape function type
AutoescapeFunc = Callable[[Any], str]# Default autoescape mode
_DEFAULT_AUTOESCAPE = "xhtml_escape"
# Whitespace modes
WHITESPACE_SINGLE = "single"
WHITESPACE_ONELINE = "oneline"
WHITESPACE_ALL = "all"
# Template file extensions
_TEMPLATE_EXTENSIONS = ['.html', '.htm', '.xml']class ParseError(Exception):
"""Exception for template parsing errors."""
def __init__(self, message: str, filename: str = None, lineno: int = None):
"""
Initialize parse error.
Args:
message: Error message
filename: Template filename
lineno: Line number where error occurred
"""
class TemplateNotFoundError(Exception):
"""Exception when template file is not found."""
def __init__(self, name: str):
"""
Initialize template not found error.
Args:
name: Template name that was not found
"""Install with Tessl CLI
npx tessl i tessl/pypi-tornado