[pre-commit.ci lite] apply automatic fixes

This commit is contained in:
pre-commit-ci-lite[bot] 2025-04-11 03:04:22 +00:00 committed by GitHub
parent b3ae3117f9
commit 3d83d8138c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
102 changed files with 26790 additions and 26749 deletions

View file

@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Template Inheritance &#8212; Flask Documentation (3.2.x)</title>
<title>Form Validation with WTForms &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
@ -15,8 +15,8 @@
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Message Flashing" href="flashing.html" />
<link rel="prev" title="Form Validation with WTForms" href="wtforms.html" />
<link rel="next" title="Template Inheritance" href="templateinheritance.html" />
<link rel="prev" title="View Decorators" href="viewdecorators.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,80 +28,131 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="flashing.html" title="Message Flashing"
<a href="templateinheritance.html" title="Template Inheritance"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="wtforms.html" title="Form Validation with WTForms"
<a href="viewdecorators.html" title="View Decorators"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Patterns for Flask</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Template Inheritance</a></li>
<li class="nav-item nav-item-this"><a href="">Form Validation with WTForms</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="template-inheritance">
<h1>Template Inheritance<a class="headerlink" href="#template-inheritance" title="Link to this heading"></a></h1>
<p>The most powerful part of Jinja is template inheritance. Template inheritance
allows you to build a base “skeleton” template that contains all the common
elements of your site and defines <strong>blocks</strong> that child templates can override.</p>
<p>Sounds complicated but is very basic. Its easiest to understand it by starting
with an example.</p>
<section id="base-template">
<h2>Base Template<a class="headerlink" href="#base-template" title="Link to this heading"></a></h2>
<p>This template, which well call <code class="file docutils literal notranslate"><span class="pre">layout.html</span></code>, defines a simple HTML skeleton
document that you might use for a simple two-column page. Its the job of
“child” templates to fill the empty blocks with content:</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="cp">&lt;!doctype html&gt;</span>
<span class="p">&lt;</span><span class="nt">html</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">head</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">head</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&quot;stylesheet&quot;</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">url_for</span><span class="o">(</span><span class="s1">&#39;static&#39;</span><span class="o">,</span> <span class="nv">filename</span><span class="o">=</span><span class="s1">&#39;style.css&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">title</span><span class="p">&gt;</span><span class="cp">{%</span> <span class="k">block</span> <span class="nv">title</span> <span class="cp">%}{%</span> <span class="k">endblock</span> <span class="cp">%}</span> - My Webpage<span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
<span class="p">&lt;/</span><span class="nt">head</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">body</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;content&quot;</span><span class="p">&gt;</span><span class="cp">{%</span> <span class="k">block</span> <span class="nv">content</span> <span class="cp">%}{%</span> <span class="k">endblock</span> <span class="cp">%}</span><span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;footer&quot;</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">footer</span> <span class="cp">%}</span>
<span class="ni">&amp;copy;</span> Copyright 2010 by <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;http://domain.invalid/&quot;</span><span class="p">&gt;</span>you<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>.
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">body</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">html</span><span class="p">&gt;</span>
<section id="form-validation-with-wtforms">
<h1>Form Validation with WTForms<a class="headerlink" href="#form-validation-with-wtforms" title="Link to this heading"></a></h1>
<p>When you have to work with form data submitted by a browser view, code
quickly becomes very hard to read. There are libraries out there designed
to make this process easier to manage. One of them is <a class="reference external" href="https://wtforms.readthedocs.io/">WTForms</a> which we
will handle here. If you find yourself in the situation of having many
forms, you might want to give it a try.</p>
<p>When you are working with WTForms you have to define your forms as classes
first. I recommend breaking up the application into multiple modules
(<a class="reference internal" href="packages.html"><span class="doc">Large Applications as Packages</span></a>) for that and adding a separate module for the
forms.</p>
<div class="admonition-getting-the-most-out-of-wtforms-with-an-extension admonition">
<p class="admonition-title">Getting the most out of WTForms with an Extension</p>
<p>The <a class="reference external" href="https://flask-wtf.readthedocs.io/">Flask-WTF</a> extension expands on this pattern and adds a
few little helpers that make working with forms and Flask more
fun. You can get it from <a class="reference external" href="https://pypi.org/project/Flask-WTF/">PyPI</a>.</p>
</div>
<section id="the-forms">
<h2>The Forms<a class="headerlink" href="#the-forms" title="Link to this heading"></a></h2>
<p>This is an example form for a typical registration page:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">wtforms</span><span class="w"> </span><span class="kn">import</span> <span class="n">Form</span><span class="p">,</span> <span class="n">BooleanField</span><span class="p">,</span> <span class="n">StringField</span><span class="p">,</span> <span class="n">PasswordField</span><span class="p">,</span> <span class="n">validators</span>
<span class="k">class</span><span class="w"> </span><span class="nc">RegistrationForm</span><span class="p">(</span><span class="n">Form</span><span class="p">):</span>
<span class="n">username</span> <span class="o">=</span> <span class="n">StringField</span><span class="p">(</span><span class="s1">&#39;Username&#39;</span><span class="p">,</span> <span class="p">[</span><span class="n">validators</span><span class="o">.</span><span class="n">Length</span><span class="p">(</span><span class="nb">min</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="nb">max</span><span class="o">=</span><span class="mi">25</span><span class="p">)])</span>
<span class="n">email</span> <span class="o">=</span> <span class="n">StringField</span><span class="p">(</span><span class="s1">&#39;Email Address&#39;</span><span class="p">,</span> <span class="p">[</span><span class="n">validators</span><span class="o">.</span><span class="n">Length</span><span class="p">(</span><span class="nb">min</span><span class="o">=</span><span class="mi">6</span><span class="p">,</span> <span class="nb">max</span><span class="o">=</span><span class="mi">35</span><span class="p">)])</span>
<span class="n">password</span> <span class="o">=</span> <span class="n">PasswordField</span><span class="p">(</span><span class="s1">&#39;New Password&#39;</span><span class="p">,</span> <span class="p">[</span>
<span class="n">validators</span><span class="o">.</span><span class="n">DataRequired</span><span class="p">(),</span>
<span class="n">validators</span><span class="o">.</span><span class="n">EqualTo</span><span class="p">(</span><span class="s1">&#39;confirm&#39;</span><span class="p">,</span> <span class="n">message</span><span class="o">=</span><span class="s1">&#39;Passwords must match&#39;</span><span class="p">)</span>
<span class="p">])</span>
<span class="n">confirm</span> <span class="o">=</span> <span class="n">PasswordField</span><span class="p">(</span><span class="s1">&#39;Repeat Password&#39;</span><span class="p">)</span>
<span class="n">accept_tos</span> <span class="o">=</span> <span class="n">BooleanField</span><span class="p">(</span><span class="s1">&#39;I accept the TOS&#39;</span><span class="p">,</span> <span class="p">[</span><span class="n">validators</span><span class="o">.</span><span class="n">DataRequired</span><span class="p">()])</span>
</pre></div>
</div>
<p>In this example, the <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">block</span> <span class="pre">%}</span></code> tags define four blocks that child templates
can fill in. All the <code class="code docutils literal notranslate"><span class="pre">block</span></code> tag does is tell the template engine that a
child template may override those portions of the template.</p>
</section>
<section id="child-template">
<h2>Child Template<a class="headerlink" href="#child-template" title="Link to this heading"></a></h2>
<p>A child template might look like this:</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">&quot;layout.html&quot;</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">title</span> <span class="cp">%}</span>Index<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">head</span> <span class="cp">%}</span>
<span class="cp">{{</span> <span class="nb">super</span><span class="o">()</span> <span class="cp">}}</span>
<span class="p">&lt;</span><span class="nt">style</span> <span class="na">type</span><span class="o">=</span><span class="s">&quot;text/css&quot;</span><span class="p">&gt;</span>
<span class="w"> </span><span class="p">.</span><span class="nc">important</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">color</span><span class="p">:</span><span class="w"> </span><span class="mh">#336699</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">&lt;/</span><span class="nt">style</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">content</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>Index<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">p</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;important&quot;</span><span class="p">&gt;</span>
Welcome on my awesome homepage.
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
<section id="in-the-view">
<h2>In the View<a class="headerlink" href="#in-the-view" title="Link to this heading"></a></h2>
<p>In the view function, the usage of this form looks like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/register&#39;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;GET&#39;</span><span class="p">,</span> <span class="s1">&#39;POST&#39;</span><span class="p">])</span>
<span class="k">def</span><span class="w"> </span><span class="nf">register</span><span class="p">():</span>
<span class="n">form</span> <span class="o">=</span> <span class="n">RegistrationForm</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="p">)</span>
<span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">method</span> <span class="o">==</span> <span class="s1">&#39;POST&#39;</span> <span class="ow">and</span> <span class="n">form</span><span class="o">.</span><span class="n">validate</span><span class="p">():</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="p">(</span><span class="n">form</span><span class="o">.</span><span class="n">username</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="n">form</span><span class="o">.</span><span class="n">email</span><span class="o">.</span><span class="n">data</span><span class="p">,</span>
<span class="n">form</span><span class="o">.</span><span class="n">password</span><span class="o">.</span><span class="n">data</span><span class="p">)</span>
<span class="n">db_session</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
<span class="n">flash</span><span class="p">(</span><span class="s1">&#39;Thanks for registering&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="n">url_for</span><span class="p">(</span><span class="s1">&#39;login&#39;</span><span class="p">))</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">&#39;register.html&#39;</span><span class="p">,</span> <span class="n">form</span><span class="o">=</span><span class="n">form</span><span class="p">)</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">{%</span> <span class="pre">extends</span> <span class="pre">%}</span></code> tag is the key here. It tells the template engine that
this template “extends” another template. When the template system evaluates
this template, first it locates the parent. The extends tag must be the
first tag in the template. To render the contents of a block defined in
the parent template, use <code class="docutils literal notranslate"><span class="pre">{{</span> <span class="pre">super()</span> <span class="pre">}}</span></code>.</p>
<p>Notice were implying that the view is using SQLAlchemy here
(<a class="reference internal" href="sqlalchemy.html"><span class="doc">SQLAlchemy in Flask</span></a>), but thats not a requirement, of course. Adapt
the code as necessary.</p>
<p>Things to remember:</p>
<ol class="arabic simple">
<li><p>create the form from the request <code class="xref py py-attr docutils literal notranslate"><span class="pre">form</span></code> value if
the data is submitted via the HTTP <code class="docutils literal notranslate"><span class="pre">POST</span></code> method and
<code class="xref py py-attr docutils literal notranslate"><span class="pre">args</span></code> if the data is submitted as <code class="docutils literal notranslate"><span class="pre">GET</span></code>.</p></li>
<li><p>to validate the data, call the <code class="xref py py-func docutils literal notranslate"><span class="pre">validate()</span></code>
method, which will return <code class="docutils literal notranslate"><span class="pre">True</span></code> if the data validates, <code class="docutils literal notranslate"><span class="pre">False</span></code>
otherwise.</p></li>
<li><p>to access individual values from the form, access <code class="code docutils literal notranslate"><span class="pre">form.&lt;NAME&gt;.data</span></code>.</p></li>
</ol>
</section>
<section id="forms-in-templates">
<h2>Forms in Templates<a class="headerlink" href="#forms-in-templates" title="Link to this heading"></a></h2>
<p>Now to the template side. When you pass the form to the templates, you can
easily render them there. Look at the following example template to see
how easy this is. WTForms does half the form generation for us already.
To make it even nicer, we can write a macro that renders a field with
label and a list of errors if there are any.</p>
<p>Heres an example <code class="file docutils literal notranslate"><span class="pre">_formhelpers.html</span></code> template with such a macro:</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">macro</span> <span class="nv">render_field</span><span class="o">(</span><span class="nv">field</span><span class="o">)</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">dt</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">field.label</span> <span class="cp">}}</span>
<span class="p">&lt;</span><span class="nt">dd</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">field</span><span class="o">(**</span><span class="nv">kwargs</span><span class="o">)|</span><span class="nf">safe</span> <span class="cp">}}</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">field.errors</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">ul</span> <span class="na">class</span><span class="o">=</span><span class="s">errors</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">error</span> <span class="k">in</span> <span class="nv">field.errors</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">li</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">error</span> <span class="cp">}}</span><span class="p">&lt;/</span><span class="nt">li</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
<span class="p">&lt;/</span><span class="nt">ul</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="p">&lt;/</span><span class="nt">dd</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endmacro</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>This macro accepts a couple of keyword arguments that are forwarded to
WTForms field function, which renders the field for us. The keyword
arguments will be inserted as HTML attributes. So, for example, you can
call <code class="docutils literal notranslate"><span class="pre">render_field(form.username,</span> <span class="pre">class='username')</span></code> to add a class to
the input element. Note that WTForms returns standard Python strings,
so we have to tell Jinja2 that this data is already HTML-escaped with
the <code class="docutils literal notranslate"><span class="pre">|safe</span></code> filter.</p>
<p>Here is the <code class="file docutils literal notranslate"><span class="pre">register.html</span></code> template for the function we used above, which
takes advantage of the <code class="file docutils literal notranslate"><span class="pre">_formhelpers.html</span></code> template:</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">from</span> <span class="s2">&quot;_formhelpers.html&quot;</span> <span class="k">import</span> <span class="nv">render_field</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">form</span> <span class="na">method</span><span class="o">=</span><span class="s">post</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">dl</span><span class="p">&gt;</span>
<span class="cp">{{</span> <span class="nv">render_field</span><span class="o">(</span><span class="nv">form.username</span><span class="o">)</span> <span class="cp">}}</span>
<span class="cp">{{</span> <span class="nv">render_field</span><span class="o">(</span><span class="nv">form.email</span><span class="o">)</span> <span class="cp">}}</span>
<span class="cp">{{</span> <span class="nv">render_field</span><span class="o">(</span><span class="nv">form.password</span><span class="o">)</span> <span class="cp">}}</span>
<span class="cp">{{</span> <span class="nv">render_field</span><span class="o">(</span><span class="nv">form.confirm</span><span class="o">)</span> <span class="cp">}}</span>
<span class="cp">{{</span> <span class="nv">render_field</span><span class="o">(</span><span class="nv">form.accept_tos</span><span class="o">)</span> <span class="cp">}}</span>
<span class="p">&lt;/</span><span class="nt">dl</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">submit</span> <span class="na">value</span><span class="o">=</span><span class="s">Register</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>For more information about WTForms, head over to the <a class="reference external" href="https://wtforms.readthedocs.io/">WTForms
website</a>.</p>
</section>
</section>
@ -113,18 +164,19 @@ the parent template, use <code class="docutils literal notranslate"><span class=
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Template Inheritance</a><ul>
<li><a class="reference internal" href="#base-template">Base Template</a></li>
<li><a class="reference internal" href="#child-template">Child Template</a></li>
<li><a class="reference internal" href="#">Form Validation with WTForms</a><ul>
<li><a class="reference internal" href="#the-forms">The Forms</a></li>
<li><a class="reference internal" href="#in-the-view">In the View</a></li>
<li><a class="reference internal" href="#forms-in-templates">Forms in Templates</a></li>
</ul>
</li>
</ul>
@ -134,8 +186,8 @@ the parent template, use <code class="docutils literal notranslate"><span class=
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="wtforms.html" title="previous chapter">Form Validation with WTForms</a>
<li>Next: <a href="flashing.html" title="next chapter">Message Flashing</a></ul>
<li>Previous: <a href="viewdecorators.html" title="previous chapter">View Decorators</a>
<li>Next: <a href="templateinheritance.html" title="next chapter">Template Inheritance</a></ul>
</li>
</ul>
</li>
@ -159,4 +211,4 @@ the parent template, use <code class="docutils literal notranslate"><span class=
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>