1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Streaming Interface — Jinja Documentation</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="style.css" type="text/css">
<style type="text/css">
.syntax { background: #ffffff; }
.syntax .c { color: #888888 } /* Comment */
.syntax .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.syntax .k { color: #008800; font-weight: bold } /* Keyword */
.syntax .cm { color: #888888 } /* Comment.Multiline */
.syntax .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.syntax .c1 { color: #888888 } /* Comment.Single */
.syntax .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.syntax .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.syntax .ge { font-style: italic } /* Generic.Emph */
.syntax .gr { color: #aa0000 } /* Generic.Error */
.syntax .gh { color: #303030 } /* Generic.Heading */
.syntax .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.syntax .go { color: #888888 } /* Generic.Output */
.syntax .gp { color: #555555 } /* Generic.Prompt */
.syntax .gs { font-weight: bold } /* Generic.Strong */
.syntax .gu { color: #606060 } /* Generic.Subheading */
.syntax .gt { color: #aa0000 } /* Generic.Traceback */
.syntax .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.syntax .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.syntax .kp { color: #008800 } /* Keyword.Pseudo */
.syntax .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.syntax .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.syntax .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.syntax .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.syntax .na { color: #336699 } /* Name.Attribute */
.syntax .nb { color: #003388 } /* Name.Builtin */
.syntax .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.syntax .no { color: #003366; font-weight: bold } /* Name.Constant */
.syntax .nd { color: #555555 } /* Name.Decorator */
.syntax .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.syntax .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.syntax .nl { color: #336699; font-style: italic } /* Name.Label */
.syntax .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.syntax .py { color: #336699; font-weight: bold } /* Name.Property */
.syntax .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.syntax .nv { color: #336699 } /* Name.Variable */
.syntax .ow { color: #008800 } /* Operator.Word */
.syntax .w { color: #bbbbbb } /* Text.Whitespace */
.syntax .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.syntax .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.syntax .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.syntax .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.syntax .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.syntax .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.syntax .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.syntax .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.syntax .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.syntax .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.syntax .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.syntax .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.syntax .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.syntax .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.syntax .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.syntax .bp { color: #003388 } /* Name.Builtin.Pseudo */
.syntax .vc { color: #336699 } /* Name.Variable.Class */
.syntax .vg { color: #dd7700 } /* Name.Variable.Global */
.syntax .vi { color: #3333bb } /* Name.Variable.Instance */
.syntax .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
</style>
</head>
<body>
<div id="content">
<h1 class="heading"><span>Jinja</span></h1>
<h2 class="subheading">Streaming Interface</h2>
<div id="toc">
<h2>Navigation</h2>
<ul>
<li><a href="index.html">back to index</a></li>
</ul>
</div>
<div id="contentwrapper">
<p>With Jinja 1.1 onwards it's possible to stream the template output. This is
usually a bad idea because it's slower than <cite>render()</cite> but there are some
situations where it's useful.</p>
<p>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.</p>
<p>The streaming interface is straightforward. Instead of using <cite>render()</cite> you
can call <cite>stream()</cite> which does pretty much the same but doesn't return a
string but a <cite>TemplateStream</cite>:</p>
<div class="syntax"><pre><span class="gp">>>> </span><span class="n">tmpl</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">from_string</span><span class="p">(</span><span class="s">"<ul>{</span><span class="si">% f</span><span class="s">or item in seq %}</span><span class="se">\n</span><span class="s"> <li>{{ loop.index "</span>
<span class="gp">... </span> <span class="s">"}} - {{ item }}</li></span><span class="se">\n</span><span class="s">{</span><span class="si">%- e</span><span class="s">ndfor %}</ul>"</span><span class="p">)</span>
<span class="gp">>>> </span><span class="n">stream</span> <span class="o">=</span> <span class="n">tmpl</span><span class="o">.</span><span class="n">stream</span><span class="p">(</span><span class="n">seq</span><span class="o">=</span><span class="nb">range</span><span class="p">(</span><span class="mf">4</span><span class="p">))</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
<span class="go">'<ul>'</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
<span class="go">u'\n <li>1 - 0</li>'</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
<span class="go">u'\n <li>2 - 1</li>'</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
<span class="go">u'\n <li>3 - 2</li>'</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
<span class="go">u'\n <li>4 - 3</li>'</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
<span class="go">'</ul>'</span>
</pre></div>
<p>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
<cite>print</cite> tag too. The only exception is the variable substitution syntax which
is inserted into the template text data.</p>
<p>Because some protocols like <cite>WSGI</cite> 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 <cite>enable_buffering</cite> and passing it the buffer
size which must be greater than one:</p>
<div class="syntax"><pre><span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">enable_buffering</span><span class="p">(</span><span class="n">size</span><span class="o">=</span><span class="mf">3</span><span class="p">)</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
<span class="go">u'<ul>\n <li>1 - 0</li>\n <li>2 - 1</li>'</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
<span class="go">u'\n <li>3 - 2</li>\n <li>4 - 3</li></ul>'</span>
</pre></div>
<p>This will buffer 3 events before yielding. Disabling buffering works using the
<cite>disable_buffering</cite> 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 <cite>.buffered</cite> property:</p>
<div class="syntax"><pre><span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">buffered</span>
<span class="go">False</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">enable_buffering</span><span class="p">(</span><span class="mf">20</span><span class="p">)</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">buffered</span>
<span class="go">True</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">disable_buffering</span><span class="p">()</span>
<span class="gp">>>> </span><span class="n">stream</span><span class="o">.</span><span class="n">buffered</span>
<span class="go">False</span>
</pre></div>
<div class="admonition-note admonition">
<p class="first admonition-title">Note</p>
<p>Jinja uses buffering internally for some constructs like macros. A macro
call is yielded as one event, independently of the internal structure.</p>
<p class="last">The same applies to recursive for loops and <cite>{% filter %}</cite> tags.</p>
</div>
</div>
</div>
</body>
<!-- generated on: 2007-11-17 18:18:07.824343
file id: streaming -->
</html>
|