Jinja
Streaming Interface
Navigation
With Jinja 1.1 onwards it's possible to stream the template output. This is usually a bad idea because it's slower than render() but there are some situations where it's useful.
If you for example generate a file with a couple of megabytes you may want to pass the stream to the WSGI interface in order to keep the amount of memory used low and deliver the output to the browser as fast as possible.
The streaming interface is straightforward. Instead of using render() you can call stream() which does pretty much the same but doesn't return a string but a TemplateStream:
>>> tmpl = env.from_string("<ul>{% for item in seq %}\n <li>{{ loop.index " ... "}} - {{ item }}</li>\n{%- endfor %}</ul>") >>> stream = tmpl.stream(seq=range(4)) >>> stream.next() '<ul>' >>> stream.next() u'\n <li>1 - 0</li>' >>> stream.next() u'\n <li>2 - 1</li>' >>> stream.next() u'\n <li>3 - 2</li>' >>> stream.next() u'\n <li>4 - 3</li>' >>> stream.next() '</ul>'
As you can see each iteration is threated as template event here. But also other tags trigger events. Basically every tag yields one event, the print tag too. The only exception is the variable substitution syntax which is inserted into the template text data.
Because some protocols like WSGI flush after each iteration if passed as response iterable it's better to buffer some events internally. You can do this by enable buffering using enable_buffering and passing it the buffer size which must be greater than one:
>>> stream.enable_buffering(size=3) >>> stream.next() u'<ul>\n <li>1 - 0</li>\n <li>2 - 1</li>' >>> stream.next() u'\n <li>3 - 2</li>\n <li>4 - 3</li></ul>'
This will buffer 3 events before yielding. Disabling buffering works using the disable_buffering method. You can enable and disable buffering on the fly also if you have already iterated over that stream. To check if you are in buffered or unbuffered mode you can use the .buffered property:
>>> stream.buffered False >>> stream.enable_buffering(20) >>> stream.buffered True >>> stream.disable_buffering() >>> stream.buffered False
Note
Jinja uses buffering internally for some constructs like macros. A macro call is yielded as one event, independently of the internal structure.
The same applies to recursive for loops and {% filter %} tags.