[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

@ -1,158 +1,252 @@
<!DOCTYPE html>
<html lang="en" data-content_root="../">
<html lang="en" data-content_root="./">
<head>
<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>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>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<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="Template Inheritance" href="templateinheritance.html" />
<link rel="prev" title="View Decorators" href="viewdecorators.html" />
<title>The Request Context &#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>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="_static/describe_version.js?v=fa7f30d0"></script>
<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="Modular Applications with Blueprints" href="blueprints.html" />
<link rel="prev" title="The Application Context" href="appcontext.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="templateinheritance.html" title="Template Inheritance"
<a href="blueprints.html" title="Modular Applications with Blueprints"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="viewdecorators.html" title="View Decorators"
<a href="appcontext.html" title="The Application Context"
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="">Form Validation with WTForms</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-this"><a href="">The Request Context</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<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>
<section id="the-request-context">
<h1>The Request Context<a class="headerlink" href="#the-request-context" title="Link to this heading"></a></h1>
<p>The request context keeps track of the request-level data during a
request. Rather than passing the request object to each function that
runs during a request, the <a class="reference internal" href="api.html#flask.request" title="flask.request"><code class="xref py py-data docutils literal notranslate"><span class="pre">request</span></code></a> and <a class="reference internal" href="api.html#flask.session" title="flask.session"><code class="xref py py-data docutils literal notranslate"><span class="pre">session</span></code></a> proxies
are accessed instead.</p>
<p>This is similar to <a class="reference internal" href="appcontext.html"><span class="doc">The Application Context</span></a>, which keeps track of the
application-level data independent of a request. A corresponding
application context is pushed when a request context is pushed.</p>
<section id="purpose-of-the-context">
<h2>Purpose of the Context<a class="headerlink" href="#purpose-of-the-context" title="Link to this heading"></a></h2>
<p>When the <a class="reference internal" href="api.html#flask.Flask" title="flask.Flask"><code class="xref py py-class docutils literal notranslate"><span class="pre">Flask</span></code></a> application handles a request, it creates a
<a class="reference internal" href="api.html#flask.Request" title="flask.Request"><code class="xref py py-class docutils literal notranslate"><span class="pre">Request</span></code></a> object based on the environment it received from the
WSGI server. Because a <em>worker</em> (thread, process, or coroutine depending
on the server) handles only one request at a time, the request data can
be considered global to that worker during that request. Flask uses the
term <em>context local</em> for this.</p>
<p>Flask automatically <em>pushes</em> a request context when handling a request.
View functions, error handlers, and other functions that run during a
request will have access to the <a class="reference internal" href="api.html#flask.request" title="flask.request"><code class="xref py py-data docutils literal notranslate"><span class="pre">request</span></code></a> proxy, which points to
the request object for the current request.</p>
</section>
<section id="lifetime-of-the-context">
<h2>Lifetime of the Context<a class="headerlink" href="#lifetime-of-the-context" title="Link to this heading"></a></h2>
<p>When a Flask application begins handling a request, it pushes a request
context, which also pushes an <a class="reference internal" href="appcontext.html"><span class="doc">app context</span></a>. When the
request ends it pops the request context then the application context.</p>
<p>The context is unique to each thread (or other worker type).
<a class="reference internal" href="api.html#flask.request" title="flask.request"><code class="xref py py-data docutils literal notranslate"><span class="pre">request</span></code></a> cannot be passed to another thread, the other thread has
a different context space and will not know about the request the parent
thread was pointing to.</p>
<p>Context locals are implemented using Pythons <a class="reference external" href="https://docs.python.org/3/library/contextvars.html#module-contextvars" title="(in Python v3.13)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">contextvars</span></code></a> and
Werkzeugs <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/local/#werkzeug.local.LocalProxy" title="(in Werkzeug v3.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">LocalProxy</span></code></a>. Python manages the
lifetime of context vars automatically, and local proxy wraps that
low-level interface to make the data easier to work with.</p>
</section>
<section id="manually-push-a-context">
<h2>Manually Push a Context<a class="headerlink" href="#manually-push-a-context" title="Link to this heading"></a></h2>
<p>If you try to access <a class="reference internal" href="api.html#flask.request" title="flask.request"><code class="xref py py-data docutils literal notranslate"><span class="pre">request</span></code></a>, or anything that uses it, outside
a request context, youll get this error message:</p>
<div class="highlight-pytb notranslate"><div class="highlight"><pre><span></span><span class="x">RuntimeError: Working outside of request context.</span>
<span class="x">This typically means that you attempted to use functionality that</span>
<span class="x">needed an active HTTP request. Consult the documentation on testing</span>
<span class="x">for information about how to avoid this problem.</span>
</pre></div>
</div>
<p>This should typically only happen when testing code that expects an
active request. One option is to use the
<a class="reference internal" href="api.html#flask.Flask.test_client" title="flask.Flask.test_client"><code class="xref py py-meth docutils literal notranslate"><span class="pre">test</span> <span class="pre">client</span></code></a> to simulate a full request. Or
you can use <a class="reference internal" href="api.html#flask.Flask.test_request_context" title="flask.Flask.test_request_context"><code class="xref py py-meth docutils literal notranslate"><span class="pre">test_request_context()</span></code></a> in a <code class="docutils literal notranslate"><span class="pre">with</span></code> block, and
everything that runs in the block will have access to <a class="reference internal" href="api.html#flask.request" title="flask.request"><code class="xref py py-data docutils literal notranslate"><span class="pre">request</span></code></a>,
populated with your test data.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">generate_report</span><span class="p">(</span><span class="n">year</span><span class="p">):</span>
<span class="nb">format</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;format&quot;</span><span class="p">)</span>
<span class="o">...</span>
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">test_request_context</span><span class="p">(</span>
<span class="s2">&quot;/make_report/2017&quot;</span><span class="p">,</span> <span class="n">query_string</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;format&quot;</span><span class="p">:</span> <span class="s2">&quot;short&quot;</span><span class="p">}</span>
<span class="p">):</span>
<span class="n">generate_report</span><span class="p">()</span>
</pre></div>
</div>
<p>If you see that error somewhere else in your code not related to
testing, it most likely indicates that you should move that code into a
view function.</p>
<p>For information on how to use the request context from the interactive
Python shell, see <a class="reference internal" href="shell.html"><span class="doc">Working with the Shell</span></a>.</p>
</section>
<section id="how-the-context-works">
<h2>How the Context Works<a class="headerlink" href="#how-the-context-works" title="Link to this heading"></a></h2>
<p>The <a class="reference internal" href="api.html#flask.Flask.wsgi_app" title="flask.Flask.wsgi_app"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Flask.wsgi_app()</span></code></a> method is called to handle each request. It
manages the contexts during the request. Internally, the request and
application contexts work like stacks. When contexts are pushed, the
proxies that depend on them are available and point at information from
the top item.</p>
<p>When the request starts, a <a class="reference internal" href="api.html#flask.ctx.RequestContext" title="flask.ctx.RequestContext"><code class="xref py py-class docutils literal notranslate"><span class="pre">RequestContext</span></code></a> is created and
pushed, which creates and pushes an <a class="reference internal" href="api.html#flask.ctx.AppContext" title="flask.ctx.AppContext"><code class="xref py py-class docutils literal notranslate"><span class="pre">AppContext</span></code></a> first if
a context for that application is not already the top context. While
these contexts are pushed, the <a class="reference internal" href="api.html#flask.current_app" title="flask.current_app"><code class="xref py py-data docutils literal notranslate"><span class="pre">current_app</span></code></a>, <a class="reference internal" href="api.html#flask.g" title="flask.g"><code class="xref py py-data docutils literal notranslate"><span class="pre">g</span></code></a>,
<a class="reference internal" href="api.html#flask.request" title="flask.request"><code class="xref py py-data docutils literal notranslate"><span class="pre">request</span></code></a>, and <a class="reference internal" href="api.html#flask.session" title="flask.session"><code class="xref py py-data docutils literal notranslate"><span class="pre">session</span></code></a> proxies are available to the
original thread handling the request.</p>
<p>Other contexts may be pushed to change the proxies during a request.
While this is not a common pattern, it can be used in advanced
applications to, for example, do internal redirects or chain different
applications together.</p>
<p>After the request is dispatched and a response is generated and sent,
the request context is popped, which then pops the application context.
Immediately before they are popped, the <a class="reference internal" href="api.html#flask.Flask.teardown_request" title="flask.Flask.teardown_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">teardown_request()</span></code></a>
and <a class="reference internal" href="api.html#flask.Flask.teardown_appcontext" title="flask.Flask.teardown_appcontext"><code class="xref py py-meth docutils literal notranslate"><span class="pre">teardown_appcontext()</span></code></a> functions are executed. These
execute even if an unhandled exception occurred during dispatch.</p>
</section>
<section id="callbacks-and-errors">
<span id="id1"></span><h2>Callbacks and Errors<a class="headerlink" href="#callbacks-and-errors" title="Link to this heading"></a></h2>
<p>Flask dispatches a request in multiple stages which can affect the
request, response, and how errors are handled. The contexts are active
during all of these stages.</p>
<p>A <a class="reference internal" href="api.html#flask.Blueprint" title="flask.Blueprint"><code class="xref py py-class docutils literal notranslate"><span class="pre">Blueprint</span></code></a> can add handlers for these events that are specific
to the blueprint. The handlers for a blueprint will run if the blueprint
owns the route that matches the request.</p>
<ol class="arabic simple">
<li><p>Before each request, <a class="reference internal" href="api.html#flask.Flask.before_request" title="flask.Flask.before_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">before_request()</span></code></a> functions are
called. If one of these functions return a value, the other
functions are skipped. The return value is treated as the response
and the view function is not called.</p></li>
<li><p>If the <a class="reference internal" href="api.html#flask.Flask.before_request" title="flask.Flask.before_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">before_request()</span></code></a> functions did not return a
response, the view function for the matched route is called and
returns a response.</p></li>
<li><p>The return value of the view is converted into an actual response
object and passed to the <a class="reference internal" href="api.html#flask.Flask.after_request" title="flask.Flask.after_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">after_request()</span></code></a>
functions. Each function returns a modified or new response object.</p></li>
<li><p>After the response is returned, the contexts are popped, which calls
the <a class="reference internal" href="api.html#flask.Flask.teardown_request" title="flask.Flask.teardown_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">teardown_request()</span></code></a> and
<a class="reference internal" href="api.html#flask.Flask.teardown_appcontext" title="flask.Flask.teardown_appcontext"><code class="xref py py-meth docutils literal notranslate"><span class="pre">teardown_appcontext()</span></code></a> functions. These functions are
called even if an unhandled exception was raised at any point above.</p></li>
</ol>
<p>If an exception is raised before the teardown functions, Flask tries to
match it with an <a class="reference internal" href="api.html#flask.Flask.errorhandler" title="flask.Flask.errorhandler"><code class="xref py py-meth docutils literal notranslate"><span class="pre">errorhandler()</span></code></a> function to handle the
exception and return a response. If no error handler is found, or the
handler itself raises an exception, Flask returns a generic
<code class="docutils literal notranslate"><span class="pre">500</span> <span class="pre">Internal</span> <span class="pre">Server</span> <span class="pre">Error</span></code> response. The teardown functions are still
called, and are passed the exception object.</p>
<p>If debug mode is enabled, unhandled exceptions are not converted to a
<code class="docutils literal notranslate"><span class="pre">500</span></code> response and instead are propagated to the WSGI server. This
allows the development server to present the interactive debugger with
the traceback.</p>
<section id="teardown-callbacks">
<h3>Teardown Callbacks<a class="headerlink" href="#teardown-callbacks" title="Link to this heading"></a></h3>
<p>The teardown callbacks are independent of the request dispatch, and are
instead called by the contexts when they are popped. The functions are
called even if there is an unhandled exception during dispatch, and for
manually pushed contexts. This means there is no guarantee that any
other parts of the request dispatch have run first. Be sure to write
these functions in a way that does not depend on other callbacks and
will not fail.</p>
<p>During testing, it can be useful to defer popping the contexts after the
request ends, so that their data can be accessed in the test function.
Use the <a class="reference internal" href="api.html#flask.Flask.test_client" title="flask.Flask.test_client"><code class="xref py py-meth docutils literal notranslate"><span class="pre">test_client()</span></code></a> as a <code class="docutils literal notranslate"><span class="pre">with</span></code> block to preserve the
contexts until the <code class="docutils literal notranslate"><span class="pre">with</span></code> block exits.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">request</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">hello</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;during view&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="s1">&#39;Hello, World!&#39;</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">teardown_request</span>
<span class="k">def</span><span class="w"> </span><span class="nf">show_teardown</span><span class="p">(</span><span class="n">exception</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;after with block&#39;</span><span class="p">)</span>
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">test_request_context</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;during with block&#39;</span><span class="p">)</span>
<span class="c1"># teardown functions are called after the context with block exits</span>
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">test_client</span><span class="p">()</span> <span class="k">as</span> <span class="n">client</span><span class="p">:</span>
<span class="n">client</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">)</span>
<span class="c1"># the contexts are not popped even though the request ended</span>
<span class="nb">print</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">path</span><span class="p">)</span>
<span class="c1"># the contexts are popped and teardown functions are called after</span>
<span class="c1"># the client with block exits</span>
</pre></div>
</div>
</section>
<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>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>
<section id="signals">
<h3>Signals<a class="headerlink" href="#signals" title="Link to this heading"></a></h3>
<p>The following signals are sent:</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>
<li><p><a class="reference internal" href="api.html#flask.request_started" title="flask.request_started"><code class="xref py py-data docutils literal notranslate"><span class="pre">request_started</span></code></a> is sent before the <a class="reference internal" href="api.html#flask.Flask.before_request" title="flask.Flask.before_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">before_request()</span></code></a> functions
are called.</p></li>
<li><p><a class="reference internal" href="api.html#flask.request_finished" title="flask.request_finished"><code class="xref py py-data docutils literal notranslate"><span class="pre">request_finished</span></code></a> is sent after the <a class="reference internal" href="api.html#flask.Flask.after_request" title="flask.Flask.after_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">after_request()</span></code></a> functions
are called.</p></li>
<li><p><a class="reference internal" href="api.html#flask.got_request_exception" title="flask.got_request_exception"><code class="xref py py-data docutils literal notranslate"><span class="pre">got_request_exception</span></code></a> is sent when an exception begins to be handled, but
before an <a class="reference internal" href="api.html#flask.Flask.errorhandler" title="flask.Flask.errorhandler"><code class="xref py py-meth docutils literal notranslate"><span class="pre">errorhandler()</span></code></a> is looked up or called.</p></li>
<li><p><a class="reference internal" href="api.html#flask.request_tearing_down" title="flask.request_tearing_down"><code class="xref py py-data docutils literal notranslate"><span class="pre">request_tearing_down</span></code></a> is sent after the <a class="reference internal" href="api.html#flask.Flask.teardown_request" title="flask.Flask.teardown_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">teardown_request()</span></code></a>
functions are called.</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>
</section>
<section id="notes-on-proxies">
<span id="id2"></span><h2>Notes On Proxies<a class="headerlink" href="#notes-on-proxies" title="Link to this heading"></a></h2>
<p>Some of the objects provided by Flask are proxies to other objects. The
proxies are accessed in the same way for each worker thread, but
point to the unique object bound to each worker behind the scenes as
described on this page.</p>
<p>Most of the time you dont have to care about that, but there are some
exceptions where it is good to know that this object is actually a proxy:</p>
<ul class="simple">
<li><p>The proxy objects cannot fake their type as the actual object types.
If you want to perform instance checks, you have to do that on the
object being proxied.</p></li>
<li><p>The reference to the proxied object is needed in some situations,
such as sending <a class="reference internal" href="signals.html"><span class="doc">Signals</span></a> or passing data to a background
thread.</p></li>
</ul>
<p>If you need to access the underlying object that is proxied, use the
<code class="xref py py-meth docutils literal notranslate"><span class="pre">_get_current_object()</span></code> method:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">app</span> <span class="o">=</span> <span class="n">current_app</span><span class="o">.</span><span class="n">_get_current_object</span><span class="p">()</span>
<span class="n">my_signal</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">app</span><span class="p">)</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>
@ -164,38 +258,42 @@ website</a>.</p>
<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"/>
<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="#">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>
<li><a class="reference internal" href="#">The Request Context</a><ul>
<li><a class="reference internal" href="#purpose-of-the-context">Purpose of the Context</a></li>
<li><a class="reference internal" href="#lifetime-of-the-context">Lifetime of the Context</a></li>
<li><a class="reference internal" href="#manually-push-a-context">Manually Push a Context</a></li>
<li><a class="reference internal" href="#how-the-context-works">How the Context Works</a></li>
<li><a class="reference internal" href="#callbacks-and-errors">Callbacks and Errors</a><ul>
<li><a class="reference internal" href="#teardown-callbacks">Teardown Callbacks</a></li>
<li><a class="reference internal" href="#signals">Signals</a></li>
</ul>
</li>
<li><a class="reference internal" href="#notes-on-proxies">Notes On Proxies</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<li><a href="index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</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>
<li>Previous: <a href="appcontext.html" title="previous chapter">The Application Context</a>
<li>Next: <a href="blueprints.html" title="next chapter">Modular Applications with Blueprints</a>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<form class="search" action="search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
@ -211,4 +309,4 @@ website</a>.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>