0
# Template Engine
1
2
Server-side template engine with automatic escaping, inheritance, and integration with the web framework. Supports both file-based and in-memory templates.
3
4
## Capabilities
5
6
### Template Compilation
7
8
Template compilation and rendering with support for template inheritance, automatic escaping, and custom filters.
9
10
```python { .api }
11
class Template:
12
"""Compiled template object."""
13
14
def __init__(self, template_string: str, name: str = "<string>", loader=None, compress_whitespace: bool = None, autoescape: str = "xhtml_escape", whitespace: str = None):
15
"""
16
Initialize template.
17
18
Args:
19
template_string: Template source code
20
name: Template name for error reporting
21
loader: Template loader instance
22
compress_whitespace: Whether to compress whitespace
23
autoescape: Autoescape function name
24
whitespace: Whitespace handling mode
25
"""
26
27
def generate(self, **kwargs) -> bytes:
28
"""
29
Generate template output.
30
31
Args:
32
**kwargs: Template variables
33
34
Returns:
35
Rendered template as bytes
36
"""
37
38
@property
39
def code(self) -> str:
40
"""Get generated Python code."""
41
42
@property
43
def name(self) -> str:
44
"""Get template name."""
45
```
46
47
### Template Loaders
48
49
Template loaders for loading templates from various sources including filesystem and dictionaries.
50
51
```python { .api }
52
class BaseLoader:
53
"""Base template loader interface."""
54
55
def __init__(self, autoescape: str = "xhtml_escape", namespace=None, whitespace: str = None):
56
"""
57
Initialize loader.
58
59
Args:
60
autoescape: Default autoescape function
61
namespace: Template namespace dict
62
whitespace: Whitespace handling mode
63
"""
64
65
def reset(self):
66
"""Clear template cache."""
67
68
def resolve_path(self, name: str, parent_path: str = None) -> str:
69
"""
70
Resolve template path.
71
72
Args:
73
name: Template name
74
parent_path: Parent template path
75
76
Returns:
77
Resolved template path
78
"""
79
80
def load(self, name: str, parent_path: str = None) -> Template:
81
"""
82
Load template by name.
83
84
Args:
85
name: Template name
86
parent_path: Parent template path
87
88
Returns:
89
Compiled Template object
90
"""
91
92
class Loader(BaseLoader):
93
"""Template loader for filesystem templates."""
94
95
def __init__(self, root_directory: str, **kwargs):
96
"""
97
Initialize filesystem loader.
98
99
Args:
100
root_directory: Root directory for templates
101
**kwargs: Additional loader options
102
"""
103
104
def get_modified_time(self, name: str) -> float:
105
"""Get template modification time."""
106
107
def load(self, name: str, parent_path: str = None) -> Template:
108
"""Load template from filesystem."""
109
110
class DictLoader(BaseLoader):
111
"""Template loader for in-memory templates."""
112
113
def __init__(self, dict: Dict[str, str], **kwargs):
114
"""
115
Initialize dictionary loader.
116
117
Args:
118
dict: Dictionary mapping template names to source code
119
**kwargs: Additional loader options
120
"""
121
122
def load(self, name: str, parent_path: str = None) -> Template:
123
"""Load template from dictionary."""
124
```
125
126
### Template Filters
127
128
Built-in template filters and utilities for template processing.
129
130
```python { .api }
131
def filter_whitespace(mode: str, text: str) -> str:
132
"""
133
Filter whitespace in template.
134
135
Args:
136
mode: Whitespace mode ("single", "oneline", "all")
137
text: Template text
138
139
Returns:
140
Filtered text
141
"""
142
143
# Built-in template functions (available in templates)
144
def xhtml_escape(value) -> str:
145
"""Escape value for HTML/XML output."""
146
147
def url_escape(value: str, plus: bool = True) -> str:
148
"""URL-encode value."""
149
150
def json_encode(value) -> str:
151
"""JSON-encode value."""
152
153
def squeeze(value: str) -> str:
154
"""Replace multiple whitespace with single space."""
155
156
def linkify(text: str, shorten: bool = False, extra_params: str = "", require_protocol: bool = False, permitted_protocols: List[str] = None) -> str:
157
"""
158
Convert URLs in text to HTML links.
159
160
Args:
161
text: Text to process
162
shorten: Whether to shorten long URLs
163
extra_params: Extra link parameters
164
require_protocol: Whether to require protocol in URLs
165
permitted_protocols: List of allowed protocols
166
167
Returns:
168
Text with HTML links
169
"""
170
```
171
172
## Template Syntax
173
174
### Basic Syntax
175
176
Templates use Python-like syntax with special delimiters:
177
178
- `{{ expression }}` - Expression output
179
- `{% statement %}` - Control statements
180
- `{# comment #}` - Comments
181
182
### Variables and Expressions
183
184
```html
185
<!-- Variable output -->
186
<h1>{{ title }}</h1>
187
<p>{{ user.name }}</p>
188
189
<!-- Expressions -->
190
<p>{{ "Hello " + user.name }}</p>
191
<p>{{ items|length }}</p>
192
<p>{{ price * 1.1 }}</p>
193
```
194
195
### Control Structures
196
197
```html
198
<!-- Conditionals -->
199
{% if user %}
200
<p>Hello, {{ user.name }}!</p>
201
{% else %}
202
<p>Please log in.</p>
203
{% end %}
204
205
<!-- Loops -->
206
{% for item in items %}
207
<li>{{ item.name }} - ${{ item.price }}</li>
208
{% end %}
209
210
<!-- Try/except -->
211
{% try %}
212
<p>{{ risky_operation() }}</p>
213
{% except %}
214
<p>Operation failed</p>
215
{% end %}
216
```
217
218
### Template Inheritance
219
220
```html
221
<!-- base.html -->
222
<!DOCTYPE html>
223
<html>
224
<head>
225
<title>{% block title %}Default Title{% end %}</title>
226
</head>
227
<body>
228
<div id="content">
229
{% block content %}{% end %}
230
</div>
231
</body>
232
</html>
233
234
<!-- child.html -->
235
{% extends "base.html" %}
236
237
{% block title %}Page Title{% end %}
238
239
{% block content %}
240
<h1>Page Content</h1>
241
<p>This is the page content.</p>
242
{% end %}
243
```
244
245
### Including Templates
246
247
```html
248
<!-- Include other templates -->
249
{% include "header.html" %}
250
<main>
251
Content here
252
</main>
253
{% include "footer.html" %}
254
```
255
256
### Filters
257
258
```html
259
<!-- Built-in filters -->
260
<p>{{ text|escape }}</p>
261
<p>{{ url|url_escape }}</p>
262
<p>{{ data|json_encode }}</p>
263
<p>{{ content|linkify }}</p>
264
265
<!-- Custom filters (defined in loader namespace) -->
266
<p>{{ date|dateformat("%Y-%m-%d") }}</p>
267
```
268
269
## Usage Examples
270
271
### Basic Template Usage
272
273
```python
274
import tornado.template
275
276
# Create template from string
277
template = tornado.template.Template("""
278
<html>
279
<head><title>{{ title }}</title></head>
280
<body>
281
<h1>{{ title }}</h1>
282
<ul>
283
{% for item in items %}
284
<li>{{ item }}</li>
285
{% end %}
286
</ul>
287
</body>
288
</html>
289
""")
290
291
# Render template
292
output = template.generate(
293
title="My Page",
294
items=["Item 1", "Item 2", "Item 3"]
295
)
296
297
print(output.decode('utf-8'))
298
```
299
300
### File-based Templates
301
302
```python
303
import tornado.template
304
import tornado.web
305
306
# Create template loader
307
loader = tornado.template.Loader("templates")
308
309
class MainHandler(tornado.web.RequestHandler):
310
def get(self):
311
# Render template file
312
self.render("index.html",
313
title="Welcome",
314
user={"name": "John Doe"})
315
316
# Application with template path
317
app = tornado.web.Application([
318
(r"/", MainHandler),
319
], template_path="templates")
320
```
321
322
### Custom Template Namespace
323
324
```python
325
import tornado.template
326
import datetime
327
328
def format_date(date):
329
return date.strftime("%B %d, %Y")
330
331
# Custom namespace with functions
332
namespace = {
333
'format_date': format_date,
334
'current_year': datetime.datetime.now().year
335
}
336
337
loader = tornado.template.Loader("templates", namespace=namespace)
338
339
# Now templates can use {{ format_date(post.date) }}
340
```
341
342
### Template with Autoescape
343
344
```python
345
import tornado.template
346
347
# Template with HTML escaping (default)
348
template = tornado.template.Template("""
349
<p>{{ user_input }}</p>
350
<p>{% raw user_input %}</p> <!-- Raw output, no escaping -->
351
""", autoescape="xhtml_escape")
352
353
# Render with user input
354
output = template.generate(user_input="<script>alert('xss')</script>")
355
```
356
357
## Types
358
359
```python { .api }
360
# Template namespace type
361
TemplateNamespace = Dict[str, Any]
362
363
# Template source type
364
TemplateSource = str
365
366
# Template name type
367
TemplateName = str
368
369
# Whitespace mode type
370
WhitespaceMode = str # "single", "oneline", "all"
371
372
# Autoescape function type
373
AutoescapeFunc = Callable[[Any], str]
374
```
375
376
## Constants
377
378
```python { .api }
379
# Default autoescape mode
380
_DEFAULT_AUTOESCAPE = "xhtml_escape"
381
382
# Whitespace modes
383
WHITESPACE_SINGLE = "single"
384
WHITESPACE_ONELINE = "oneline"
385
WHITESPACE_ALL = "all"
386
387
# Template file extensions
388
_TEMPLATE_EXTENSIONS = ['.html', '.htm', '.xml']
389
```
390
391
## Exceptions
392
393
```python { .api }
394
class ParseError(Exception):
395
"""Exception for template parsing errors."""
396
397
def __init__(self, message: str, filename: str = None, lineno: int = None):
398
"""
399
Initialize parse error.
400
401
Args:
402
message: Error message
403
filename: Template filename
404
lineno: Line number where error occurred
405
"""
406
407
class TemplateNotFoundError(Exception):
408
"""Exception when template file is not found."""
409
410
def __init__(self, name: str):
411
"""
412
Initialize template not found error.
413
414
Args:
415
name: Template name that was not found
416
"""
417
```