[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>Application Dispatching &#8212; Flask Documentation (3.2.x)</title>
<title>Background Tasks with Celery &#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="Using URL Processors" href="urlprocessors.html" />
<link rel="prev" title="Application Factories" href="appfactories.html" />
<link rel="next" title="Subclassing Flask" href="subclassing.html" />
<link rel="prev" title="Request Content Checksums" href="requestchecksum.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,186 +28,212 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="urlprocessors.html" title="Using URL Processors"
<a href="subclassing.html" title="Subclassing Flask"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="appfactories.html" title="Application Factories"
<a href="requestchecksum.html" title="Request Content Checksums"
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="">Application Dispatching</a></li>
<li class="nav-item nav-item-this"><a href="">Background Tasks with Celery</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="application-dispatching">
<h1>Application Dispatching<a class="headerlink" href="#application-dispatching" title="Link to this heading"></a></h1>
<p>Application dispatching is the process of combining multiple Flask
applications on the WSGI level. You can combine not only Flask
applications but any WSGI application. This would allow you to run a
Django and a Flask application in the same interpreter side by side if
you want. The usefulness of this depends on how the applications work
internally.</p>
<p>The fundamental difference from <a class="reference internal" href="packages.html"><span class="doc">Large Applications as Packages</span></a> is that in this case you
are running the same or different Flask applications that are entirely
isolated from each other. They run different configurations and are
dispatched on the WSGI level.</p>
<section id="working-with-this-document">
<h2>Working with this Document<a class="headerlink" href="#working-with-this-document" title="Link to this heading"></a></h2>
<p>Each of the techniques and examples below results in an <code class="docutils literal notranslate"><span class="pre">application</span></code>
object that can be run with any WSGI server. For development, use the
<code class="docutils literal notranslate"><span class="pre">flask</span> <span class="pre">run</span></code> command to start a development server. For production, see
<a class="reference internal" href="../deploying/index.html"><span class="doc">Deploying to Production</span></a>.</p>
<section id="background-tasks-with-celery">
<h1>Background Tasks with Celery<a class="headerlink" href="#background-tasks-with-celery" title="Link to this heading"></a></h1>
<p>If your application has a long running task, such as processing some uploaded data or
sending email, you dont want to wait for it to finish during a request. Instead, use a
task queue to send the necessary data to another process that will run the task in the
background while the request returns immediately.</p>
<p><a class="reference external" href="https://celery.readthedocs.io">Celery</a> is a powerful task queue that can be used for simple background tasks as well
as complex multi-stage programs and schedules. This guide will show you how to configure
Celery using Flask. Read Celerys <a class="reference external" href="https://celery.readthedocs.io/en/latest/getting-started/first-steps-with-celery.html">First Steps with Celery</a> guide to learn how to use
Celery itself.</p>
<p>The Flask repository contains <a class="reference external" href="https://github.com/pallets/flask/tree/main/examples/celery">an example</a>
based on the information on this page, which also shows how to use JavaScript to submit
tasks and poll for progress and results.</p>
<section id="install">
<h2>Install<a class="headerlink" href="#install" title="Link to this heading"></a></h2>
<p>Install Celery from PyPI, for example using pip:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ pip install celery
</pre></div>
</div>
</section>
<section id="integrate-celery-with-flask">
<h2>Integrate Celery with Flask<a class="headerlink" href="#integrate-celery-with-flask" title="Link to this heading"></a></h2>
<p>You can use Celery without any integration with Flask, but its convenient to configure
it through Flasks config, and to let tasks access the Flask application.</p>
<p>Celery uses similar ideas to Flask, with a <code class="docutils literal notranslate"><span class="pre">Celery</span></code> app object that has configuration
and registers tasks. While creating a Flask app, use the following code to create and
configure a Celery app as well.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">celery</span><span class="w"> </span><span class="kn">import</span> <span class="n">Celery</span><span class="p">,</span> <span class="n">Task</span>
<span class="k">def</span><span class="w"> </span><span class="nf">celery_init_app</span><span class="p">(</span><span class="n">app</span><span class="p">:</span> <span class="n">Flask</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Celery</span><span class="p">:</span>
<span class="k">class</span><span class="w"> </span><span class="nc">FlaskTask</span><span class="p">(</span><span class="n">Task</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="nb">object</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="nb">object</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">object</span><span class="p">:</span>
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">app_context</span><span class="p">():</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="n">celery_app</span> <span class="o">=</span> <span class="n">Celery</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">task_cls</span><span class="o">=</span><span class="n">FlaskTask</span><span class="p">)</span>
<span class="n">celery_app</span><span class="o">.</span><span class="n">config_from_object</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;CELERY&quot;</span><span class="p">])</span>
<span class="n">celery_app</span><span class="o">.</span><span class="n">set_default</span><span class="p">()</span>
<span class="n">app</span><span class="o">.</span><span class="n">extensions</span><span class="p">[</span><span class="s2">&quot;celery&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">celery_app</span>
<span class="k">return</span> <span class="n">celery_app</span>
</pre></div>
</div>
<p>This creates and returns a <code class="docutils literal notranslate"><span class="pre">Celery</span></code> app object. Celery <a class="reference external" href="https://celery.readthedocs.io/en/stable/userguide/configuration.html">configuration</a> is taken from
the <code class="docutils literal notranslate"><span class="pre">CELERY</span></code> key in the Flask configuration. The Celery app is set as the default, so
that it is seen during each request. The <code class="docutils literal notranslate"><span class="pre">Task</span></code> subclass automatically runs task
functions with a Flask app context active, so that services like your database
connections are available.</p>
<p>Heres a basic <code class="docutils literal notranslate"><span class="pre">example.py</span></code> that configures Celery to use Redis for communication. We
enable a result backend, but ignore results by default. This allows us to store results
only for tasks where we care about the result.</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="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_world</span><span class="p">():</span>
<span class="k">return</span> <span class="s1">&#39;Hello World!&#39;</span>
<span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_mapping</span><span class="p">(</span>
<span class="n">CELERY</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span>
<span class="n">broker_url</span><span class="o">=</span><span class="s2">&quot;redis://localhost&quot;</span><span class="p">,</span>
<span class="n">result_backend</span><span class="o">=</span><span class="s2">&quot;redis://localhost&quot;</span><span class="p">,</span>
<span class="n">task_ignore_result</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="p">),</span>
<span class="p">)</span>
<span class="n">celery_app</span> <span class="o">=</span> <span class="n">celery_init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
</pre></div>
</div>
<p>Point the <code class="docutils literal notranslate"><span class="pre">celery</span> <span class="pre">worker</span></code> command at this and it will find the <code class="docutils literal notranslate"><span class="pre">celery_app</span></code> object.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ celery -A example worker --loglevel INFO
</pre></div>
</div>
<p>You can also run the <code class="docutils literal notranslate"><span class="pre">celery</span> <span class="pre">beat</span></code> command to run tasks on a schedule. See Celerys
docs for more information about defining schedules.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ celery -A example beat --loglevel INFO
</pre></div>
</div>
</section>
<section id="combining-applications">
<h2>Combining Applications<a class="headerlink" href="#combining-applications" title="Link to this heading"></a></h2>
<p>If you have entirely separated applications and you want them to work next
to each other in the same Python interpreter process you can take
advantage of the <code class="xref py py-class docutils literal notranslate"><span class="pre">werkzeug.wsgi.DispatcherMiddleware</span></code>. The idea
here is that each Flask application is a valid WSGI application and they
are combined by the dispatcher middleware into a larger one that is
dispatched based on prefix.</p>
<p>For example you could have your main application run on <code class="docutils literal notranslate"><span class="pre">/</span></code> and your
backend interface on <code class="docutils literal notranslate"><span class="pre">/backend</span></code>.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">werkzeug.middleware.dispatcher</span><span class="w"> </span><span class="kn">import</span> <span class="n">DispatcherMiddleware</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">frontend_app</span><span class="w"> </span><span class="kn">import</span> <span class="n">application</span> <span class="k">as</span> <span class="n">frontend</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">backend_app</span><span class="w"> </span><span class="kn">import</span> <span class="n">application</span> <span class="k">as</span> <span class="n">backend</span>
<section id="application-factory">
<h2>Application Factory<a class="headerlink" href="#application-factory" title="Link to this heading"></a></h2>
<p>When using the Flask application factory pattern, call the <code class="docutils literal notranslate"><span class="pre">celery_init_app</span></code> function
inside the factory. It sets <code class="docutils literal notranslate"><span class="pre">app.extensions[&quot;celery&quot;]</span></code> to the Celery app object, which
can be used to get the Celery app from the Flask app returned by the factory.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">create_app</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Flask</span><span class="p">:</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="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_mapping</span><span class="p">(</span>
<span class="n">CELERY</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span>
<span class="n">broker_url</span><span class="o">=</span><span class="s2">&quot;redis://localhost&quot;</span><span class="p">,</span>
<span class="n">result_backend</span><span class="o">=</span><span class="s2">&quot;redis://localhost&quot;</span><span class="p">,</span>
<span class="n">task_ignore_result</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="p">),</span>
<span class="p">)</span>
<span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_prefixed_env</span><span class="p">()</span>
<span class="n">celery_init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<span class="k">return</span> <span class="n">app</span>
</pre></div>
</div>
<p>To use <code class="docutils literal notranslate"><span class="pre">celery</span></code> commands, Celery needs an app object, but thats no longer directly
available. Create a <code class="docutils literal notranslate"><span class="pre">make_celery.py</span></code> file that calls the Flask app factory and gets
the Celery app from the returned Flask app.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">example</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">DispatcherMiddleware</span><span class="p">(</span><span class="n">frontend</span><span class="p">,</span> <span class="p">{</span>
<span class="s1">&#39;/backend&#39;</span><span class="p">:</span> <span class="n">backend</span>
<span class="p">})</span>
<span class="n">flask_app</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
<span class="n">celery_app</span> <span class="o">=</span> <span class="n">flask_app</span><span class="o">.</span><span class="n">extensions</span><span class="p">[</span><span class="s2">&quot;celery&quot;</span><span class="p">]</span>
</pre></div>
</div>
<p>Point the <code class="docutils literal notranslate"><span class="pre">celery</span></code> command to this file.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ celery -A make_celery worker --loglevel INFO
$ celery -A make_celery beat --loglevel INFO
</pre></div>
</div>
</section>
<section id="dispatch-by-subdomain">
<h2>Dispatch by Subdomain<a class="headerlink" href="#dispatch-by-subdomain" title="Link to this heading"></a></h2>
<p>Sometimes you might want to use multiple instances of the same application
with different configurations. Assuming the application is created inside
a function and you can call that function to instantiate it, that is
really easy to implement. In order to develop your application to support
creating new instances in functions have a look at the
<a class="reference internal" href="appfactories.html"><span class="doc">Application Factories</span></a> pattern.</p>
<p>A very common example would be creating applications per subdomain. For
instance you configure your webserver to dispatch all requests for all
subdomains to your application and you then use the subdomain information
to create user-specific instances. Once you have your server set up to
listen on all subdomains you can use a very simple WSGI application to do
the dynamic application creation.</p>
<p>The perfect level for abstraction in that regard is the WSGI layer. You
write your own WSGI application that looks at the request that comes and
delegates it to your Flask application. If that application does not
exist yet, it is dynamically created and remembered.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">threading</span><span class="w"> </span><span class="kn">import</span> <span class="n">Lock</span>
<section id="defining-tasks">
<h2>Defining Tasks<a class="headerlink" href="#defining-tasks" title="Link to this heading"></a></h2>
<p>Using <code class="docutils literal notranslate"><span class="pre">&#64;celery_app.task</span></code> to decorate task functions requires access to the
<code class="docutils literal notranslate"><span class="pre">celery_app</span></code> object, which wont be available when using the factory pattern. It also
means that the decorated tasks are tied to the specific Flask and Celery app instances,
which could be an issue during testing if you change configuration for a test.</p>
<p>Instead, use Celerys <code class="docutils literal notranslate"><span class="pre">&#64;shared_task</span></code> decorator. This creates task objects that will
access whatever the “current app” is, which is a similar concept to Flasks blueprints
and app context. This is why we called <code class="docutils literal notranslate"><span class="pre">celery_app.set_default()</span></code> above.</p>
<p>Heres an example task that adds two numbers together and returns the result.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">celery</span><span class="w"> </span><span class="kn">import</span> <span class="n">shared_task</span>
<span class="k">class</span><span class="w"> </span><span class="nc">SubdomainDispatcher</span><span class="p">:</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">domain</span><span class="p">,</span> <span class="n">create_app</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">domain</span> <span class="o">=</span> <span class="n">domain</span>
<span class="bp">self</span><span class="o">.</span><span class="n">create_app</span> <span class="o">=</span> <span class="n">create_app</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lock</span> <span class="o">=</span> <span class="n">Lock</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">instances</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_application</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">host</span><span class="p">):</span>
<span class="n">host</span> <span class="o">=</span> <span class="n">host</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;:&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">assert</span> <span class="n">host</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">domain</span><span class="p">),</span> <span class="s1">&#39;Configuration error&#39;</span>
<span class="n">subdomain</span> <span class="o">=</span> <span class="n">host</span><span class="p">[:</span><span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">domain</span><span class="p">)]</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">)</span>
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">lock</span><span class="p">:</span>
<span class="n">app</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">instances</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">subdomain</span><span class="p">)</span>
<span class="k">if</span> <span class="n">app</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">app</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">create_app</span><span class="p">(</span><span class="n">subdomain</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">instances</span><span class="p">[</span><span class="n">subdomain</span><span class="p">]</span> <span class="o">=</span> <span class="n">app</span>
<span class="k">return</span> <span class="n">app</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
<span class="n">app</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_application</span><span class="p">(</span><span class="n">environ</span><span class="p">[</span><span class="s1">&#39;HTTP_HOST&#39;</span><span class="p">])</span>
<span class="k">return</span> <span class="n">app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
</pre></div>
</div>
<p>This dispatcher can then be used like this:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">myapplication</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span><span class="p">,</span> <span class="n">get_user_for_subdomain</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">werkzeug.exceptions</span><span class="w"> </span><span class="kn">import</span> <span class="n">NotFound</span>
<span class="k">def</span><span class="w"> </span><span class="nf">make_app</span><span class="p">(</span><span class="n">subdomain</span><span class="p">):</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">get_user_for_subdomain</span><span class="p">(</span><span class="n">subdomain</span><span class="p">)</span>
<span class="k">if</span> <span class="n">user</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="c1"># if there is no user for that subdomain we still have</span>
<span class="c1"># to return a WSGI application that handles that request.</span>
<span class="c1"># We can then just return the NotFound() exception as</span>
<span class="c1"># application which will render a default 404 page.</span>
<span class="c1"># You might also redirect the user to the main page then</span>
<span class="k">return</span> <span class="n">NotFound</span><span class="p">()</span>
<span class="c1"># otherwise create the application for the specific user</span>
<span class="k">return</span> <span class="n">create_app</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">SubdomainDispatcher</span><span class="p">(</span><span class="s1">&#39;example.com&#39;</span><span class="p">,</span> <span class="n">make_app</span><span class="p">)</span>
<span class="nd">@shared_task</span><span class="p">(</span><span class="n">ignore_result</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">add_together</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
</pre></div>
</div>
<p>Earlier, we configured Celery to ignore task results by default. Since we want to know
the return value of this task, we set <code class="docutils literal notranslate"><span class="pre">ignore_result=False</span></code>. On the other hand, a task
that didnt need a result, such as sending an email, wouldnt set this.</p>
</section>
<section id="dispatch-by-path">
<h2>Dispatch by Path<a class="headerlink" href="#dispatch-by-path" title="Link to this heading"></a></h2>
<p>Dispatching by a path on the URL is very similar. Instead of looking at
the <code class="docutils literal notranslate"><span class="pre">Host</span></code> header to figure out the subdomain one simply looks at the
request path up to the first slash.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">threading</span><span class="w"> </span><span class="kn">import</span> <span class="n">Lock</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">wsgiref.util</span><span class="w"> </span><span class="kn">import</span> <span class="n">shift_path_info</span>
<section id="calling-tasks">
<h2>Calling Tasks<a class="headerlink" href="#calling-tasks" title="Link to this heading"></a></h2>
<p>The decorated function becomes a task object with methods to call it in the background.
The simplest way is to use the <code class="docutils literal notranslate"><span class="pre">delay(*args,</span> <span class="pre">**kwargs)</span></code> method. See Celerys docs for
more methods.</p>
<p>A Celery worker must be running to run the task. Starting a worker is shown in the
previous sections.</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">request</span>
<span class="k">class</span><span class="w"> </span><span class="nc">PathDispatcher</span><span class="p">:</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default_app</span><span class="p">,</span> <span class="n">create_app</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">default_app</span> <span class="o">=</span> <span class="n">default_app</span>
<span class="bp">self</span><span class="o">.</span><span class="n">create_app</span> <span class="o">=</span> <span class="n">create_app</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lock</span> <span class="o">=</span> <span class="n">Lock</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">instances</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_application</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">prefix</span><span class="p">):</span>
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">lock</span><span class="p">:</span>
<span class="n">app</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">instances</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">prefix</span><span class="p">)</span>
<span class="k">if</span> <span class="n">app</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">app</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">create_app</span><span class="p">(</span><span class="n">prefix</span><span class="p">)</span>
<span class="k">if</span> <span class="n">app</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">instances</span><span class="p">[</span><span class="n">prefix</span><span class="p">]</span> <span class="o">=</span> <span class="n">app</span>
<span class="k">return</span> <span class="n">app</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
<span class="n">app</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_application</span><span class="p">(</span><span class="n">_peek_path_info</span><span class="p">(</span><span class="n">environ</span><span class="p">))</span>
<span class="k">if</span> <span class="n">app</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">shift_path_info</span><span class="p">(</span><span class="n">environ</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">app</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">default_app</span>
<span class="k">return</span> <span class="n">app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_peek_path_info</span><span class="p">(</span><span class="n">environ</span><span class="p">):</span>
<span class="n">segments</span> <span class="o">=</span> <span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;PATH_INFO&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="n">segments</span><span class="p">:</span>
<span class="k">return</span> <span class="n">segments</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">&quot;/add&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">start_add</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">object</span><span class="p">]:</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;b&quot;</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">add_together</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="k">return</span> <span class="p">{</span><span class="s2">&quot;result_id&quot;</span><span class="p">:</span> <span class="n">result</span><span class="o">.</span><span class="n">id</span><span class="p">}</span>
</pre></div>
</div>
<p>The big difference between this and the subdomain one is that this one
falls back to another application if the creator function returns <code class="docutils literal notranslate"><span class="pre">None</span></code>.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">myapplication</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span><span class="p">,</span> <span class="n">default_app</span><span class="p">,</span> <span class="n">get_user_for_prefix</span>
<p>The route doesnt get the tasks result immediately. That would defeat the purpose by
blocking the response. Instead, we return the running tasks result id, which we can use
later to get the result.</p>
</section>
<section id="getting-results">
<h2>Getting Results<a class="headerlink" href="#getting-results" title="Link to this heading"></a></h2>
<p>To fetch the result of the task we started above, well add another route that takes the
result id we returned before. We return whether the task is finished (ready), whether it
finished successfully, and what the return value (or error) was if it is finished.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">celery.result</span><span class="w"> </span><span class="kn">import</span> <span class="n">AsyncResult</span>
<span class="k">def</span><span class="w"> </span><span class="nf">make_app</span><span class="p">(</span><span class="n">prefix</span><span class="p">):</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">get_user_for_prefix</span><span class="p">(</span><span class="n">prefix</span><span class="p">)</span>
<span class="k">if</span> <span class="n">user</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">return</span> <span class="n">create_app</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/result/&lt;id&gt;&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">task_result</span><span class="p">(</span><span class="nb">id</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">object</span><span class="p">]:</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">AsyncResult</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span>
<span class="k">return</span> <span class="p">{</span>
<span class="s2">&quot;ready&quot;</span><span class="p">:</span> <span class="n">result</span><span class="o">.</span><span class="n">ready</span><span class="p">(),</span>
<span class="s2">&quot;successful&quot;</span><span class="p">:</span> <span class="n">result</span><span class="o">.</span><span class="n">successful</span><span class="p">(),</span>
<span class="s2">&quot;value&quot;</span><span class="p">:</span> <span class="n">result</span><span class="o">.</span><span class="n">result</span> <span class="k">if</span> <span class="n">result</span><span class="o">.</span><span class="n">ready</span><span class="p">()</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Now you can start the task using the first route, then poll for the result using the
second route. This keeps the Flask request workers from being blocked waiting for tasks
to finish.</p>
<p>The Flask repository contains <a class="reference external" href="https://github.com/pallets/flask/tree/main/examples/celery">an example</a>
using JavaScript to submit tasks and poll for progress and results.</p>
</section>
<section id="passing-data-to-tasks">
<h2>Passing Data to Tasks<a class="headerlink" href="#passing-data-to-tasks" title="Link to this heading"></a></h2>
<p>The “add” task above took two integers as arguments. To pass arguments to tasks, Celery
has to serialize them to a format that it can pass to other processes. Therefore,
passing complex objects is not recommended. For example, it would be impossible to pass
a SQLAlchemy model object, since that object is probably not serializable and is tied to
the session that queried it.</p>
<p>Pass the minimal amount of data necessary to fetch or recreate any complex data within
the task. Consider a task that will run when the logged in user asks for an archive of
their data. The Flask request knows the logged in user, and has the user object queried
from the database. It got that by querying the database for a given id, so the task can
do the same thing. Pass the users id rather than the user object.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@shared_task</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate_user_archive</span><span class="p">(</span><span class="n">user_id</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">user_id</span><span class="p">)</span>
<span class="o">...</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">PathDispatcher</span><span class="p">(</span><span class="n">default_app</span><span class="p">,</span> <span class="n">make_app</span><span class="p">)</span>
<span class="n">generate_user_archive</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="n">current_user</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
</pre></div>
</div>
</section>
@ -221,20 +247,23 @@ falls back to another application if the creator function returns <code class="d
<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="#">Application Dispatching</a><ul>
<li><a class="reference internal" href="#working-with-this-document">Working with this Document</a></li>
<li><a class="reference internal" href="#combining-applications">Combining Applications</a></li>
<li><a class="reference internal" href="#dispatch-by-subdomain">Dispatch by Subdomain</a></li>
<li><a class="reference internal" href="#dispatch-by-path">Dispatch by Path</a></li>
<li><a class="reference internal" href="#">Background Tasks with Celery</a><ul>
<li><a class="reference internal" href="#install">Install</a></li>
<li><a class="reference internal" href="#integrate-celery-with-flask">Integrate Celery with Flask</a></li>
<li><a class="reference internal" href="#application-factory">Application Factory</a></li>
<li><a class="reference internal" href="#defining-tasks">Defining Tasks</a></li>
<li><a class="reference internal" href="#calling-tasks">Calling Tasks</a></li>
<li><a class="reference internal" href="#getting-results">Getting Results</a></li>
<li><a class="reference internal" href="#passing-data-to-tasks">Passing Data to Tasks</a></li>
</ul>
</li>
</ul>
@ -244,8 +273,8 @@ falls back to another application if the creator function returns <code class="d
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="appfactories.html" title="previous chapter">Application Factories</a>
<li>Next: <a href="urlprocessors.html" title="next chapter">Using URL Processors</a></ul>
<li>Previous: <a href="requestchecksum.html" title="previous chapter">Request Content Checksums</a>
<li>Next: <a href="subclassing.html" title="next chapter">Subclassing Flask</a></ul>
</li>
</ul>
</li>
@ -269,4 +298,4 @@ falls back to another application if the creator function returns <code class="d
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Application Factories &#8212; Flask Documentation (3.2.x)</title>
<title>Deferred Request Callbacks &#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="Application Dispatching" href="appdispatch.html" />
<link rel="prev" title="Large Applications as Packages" href="packages.html" />
<link rel="next" title="Adding HTTP Method Overrides" href="methodoverrides.html" />
<link rel="prev" title="Streaming Contents" href="streaming.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,130 +28,62 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="appdispatch.html" title="Application Dispatching"
<a href="methodoverrides.html" title="Adding HTTP Method Overrides"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="packages.html" title="Large Applications as Packages"
<a href="streaming.html" title="Streaming Contents"
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="">Application Factories</a></li>
<li class="nav-item nav-item-this"><a href="">Deferred Request Callbacks</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="application-factories">
<h1>Application Factories<a class="headerlink" href="#application-factories" title="Link to this heading"></a></h1>
<p>If you are already using packages and blueprints for your application
(<a class="reference internal" href="../blueprints.html"><span class="doc">Modular Applications with Blueprints</span></a>) there are a couple of really nice ways to further improve
the experience. A common pattern is creating the application object when
the blueprint is imported. But if you move the creation of this object
into a function, you can then create multiple instances of this app later.</p>
<p>So why would you want to do this?</p>
<ol class="arabic simple">
<li><p>Testing. You can have instances of the application with different
settings to test every case.</p></li>
<li><p>Multiple instances. Imagine you want to run different versions of the
same application. Of course you could have multiple instances with
different configs set up in your webserver, but if you use factories,
you can have multiple instances of the same application running in the
same application process which can be handy.</p></li>
</ol>
<p>So how would you then actually implement that?</p>
<section id="basic-factories">
<h2>Basic Factories<a class="headerlink" href="#basic-factories" title="Link to this heading"></a></h2>
<p>The idea is to set up the application in a function. Like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">create_app</span><span class="p">(</span><span class="n">config_filename</span><span class="p">):</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="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_pyfile</span><span class="p">(</span><span class="n">config_filename</span><span class="p">)</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.model</span><span class="w"> </span><span class="kn">import</span> <span class="n">db</span>
<span class="n">db</span><span class="o">.</span><span class="n">init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<section id="deferred-request-callbacks">
<h1>Deferred Request Callbacks<a class="headerlink" href="#deferred-request-callbacks" title="Link to this heading"></a></h1>
<p>One of the design principles of Flask is that response objects are created and
passed down a chain of potential callbacks that can modify them or replace
them. When the request handling starts, there is no response object yet. It is
created as necessary either by a view function or by some other component in
the system.</p>
<p>What happens if you want to modify the response at a point where the response
does not exist yet? A common example for that would be a
<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> callback that wants to set a cookie on the
response object.</p>
<p>One way is to avoid the situation. Very often that is possible. For instance
you can try to move that logic into a <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>
callback instead. However, sometimes moving code there makes it
more complicated or awkward to reason about.</p>
<p>As an alternative, you can use <a class="reference internal" href="../api.html#flask.after_this_request" title="flask.after_this_request"><code class="xref py py-func docutils literal notranslate"><span class="pre">after_this_request()</span></code></a> to register
callbacks that will execute after only the current request. This way you can
defer code execution from anywhere in the application, based on the current
request.</p>
<p>At any time during a request, we can register a function to be called at the
end of the request. For example you can remember the current language of the
user in a cookie in a <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> callback:</p>
<div class="highlight-default 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">request</span><span class="p">,</span> <span class="n">after_this_request</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.views.admin</span><span class="w"> </span><span class="kn">import</span> <span class="n">admin</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.views.frontend</span><span class="w"> </span><span class="kn">import</span> <span class="n">frontend</span>
<span class="n">app</span><span class="o">.</span><span class="n">register_blueprint</span><span class="p">(</span><span class="n">admin</span><span class="p">)</span>
<span class="n">app</span><span class="o">.</span><span class="n">register_blueprint</span><span class="p">(</span><span class="n">frontend</span><span class="p">)</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">before_request</span>
<span class="k">def</span><span class="w"> </span><span class="nf">detect_user_language</span><span class="p">():</span>
<span class="n">language</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">cookies</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;user_lang&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">app</span>
</pre></div>
</div>
<p>The downside is that you cannot use the application object in the blueprints
at import time. You can however use it from within a request. How do you
get access to the application with the config? Use
<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>:</p>
<div class="highlight-default 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">current_app</span><span class="p">,</span> <span class="n">Blueprint</span><span class="p">,</span> <span class="n">render_template</span>
<span class="n">admin</span> <span class="o">=</span> <span class="n">Blueprint</span><span class="p">(</span><span class="s1">&#39;admin&#39;</span><span class="p">,</span> <span class="vm">__name__</span><span class="p">,</span> <span class="n">url_prefix</span><span class="o">=</span><span class="s1">&#39;/admin&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">language</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">language</span> <span class="o">=</span> <span class="n">guess_language_from_request</span><span class="p">()</span>
<span class="nd">@admin</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">index</span><span class="p">():</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="n">current_app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;INDEX_TEMPLATE&#39;</span><span class="p">])</span>
</pre></div>
</div>
<p>Here we look up the name of a template in the config.</p>
</section>
<section id="factories-extensions">
<h2>Factories &amp; Extensions<a class="headerlink" href="#factories-extensions" title="Link to this heading"></a></h2>
<p>Its preferable to create your extensions and app factories so that the
extension object does not initially get bound to the application.</p>
<p>Using <a class="reference external" href="https://flask-sqlalchemy.palletsprojects.com/">Flask-SQLAlchemy</a>,
as an example, you should not do something along those lines:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">create_app</span><span class="p">(</span><span class="n">config_filename</span><span class="p">):</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="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_pyfile</span><span class="p">(</span><span class="n">config_filename</span><span class="p">)</span>
<span class="c1"># when the response exists, set a cookie with the language</span>
<span class="nd">@after_this_request</span>
<span class="k">def</span><span class="w"> </span><span class="nf">remember_language</span><span class="p">(</span><span class="n">response</span><span class="p">):</span>
<span class="n">response</span><span class="o">.</span><span class="n">set_cookie</span><span class="p">(</span><span class="s1">&#39;user_lang&#39;</span><span class="p">,</span> <span class="n">language</span><span class="p">)</span>
<span class="k">return</span> <span class="n">response</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">SQLAlchemy</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<span class="n">g</span><span class="o">.</span><span class="n">language</span> <span class="o">=</span> <span class="n">language</span>
</pre></div>
</div>
<p>But, rather, in model.py (or equivalent):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">db</span> <span class="o">=</span> <span class="n">SQLAlchemy</span><span class="p">()</span>
</pre></div>
</div>
<p>and in your application.py (or equivalent):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">create_app</span><span class="p">(</span><span class="n">config_filename</span><span class="p">):</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="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_pyfile</span><span class="p">(</span><span class="n">config_filename</span><span class="p">)</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.model</span><span class="w"> </span><span class="kn">import</span> <span class="n">db</span>
<span class="n">db</span><span class="o">.</span><span class="n">init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
</pre></div>
</div>
<p>Using this design pattern, no application-specific state is stored on the
extension object, so one extension object can be used for multiple apps.
For more information about the design of extensions refer to <a class="reference internal" href="../extensiondev.html"><span class="doc">Flask Extension Development</span></a>.</p>
</section>
<section id="using-applications">
<h2>Using Applications<a class="headerlink" href="#using-applications" title="Link to this heading"></a></h2>
<p>To run such an application, you can use the <strong class="command">flask</strong> command:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ flask --app hello run
</pre></div>
</div>
<p>Flask will automatically detect the factory if it is named
<code class="docutils literal notranslate"><span class="pre">create_app</span></code> or <code class="docutils literal notranslate"><span class="pre">make_app</span></code> in <code class="docutils literal notranslate"><span class="pre">hello</span></code>. You can also pass arguments
to the factory like this:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ flask --app &#39;hello:create_app(local_auth=True)&#39; run
</pre></div>
</div>
<p>Then the <code class="docutils literal notranslate"><span class="pre">create_app</span></code> factory in <code class="docutils literal notranslate"><span class="pre">hello</span></code> is called with the keyword
argument <code class="docutils literal notranslate"><span class="pre">local_auth=True</span></code>. See <a class="reference internal" href="../cli.html"><span class="doc">Command Line Interface</span></a> for more detail.</p>
</section>
<section id="factory-improvements">
<h2>Factory Improvements<a class="headerlink" href="#factory-improvements" title="Link to this heading"></a></h2>
<p>The factory function above is not very clever, but you can improve it.
The following changes are straightforward to implement:</p>
<ol class="arabic simple">
<li><p>Make it possible to pass in configuration values for unit tests so that
you dont have to create config files on the filesystem.</p></li>
<li><p>Call a function from a blueprint when the application is setting up so
that you have a place to modify attributes of the application (like
hooking in before/after request handlers etc.)</p></li>
<li><p>Add in WSGI middlewares when the application is being created if necessary.</p></li>
</ol>
</section>
</section>
@ -162,31 +94,20 @@ hooking in before/after request handlers etc.)</p></li>
<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="#">Application Factories</a><ul>
<li><a class="reference internal" href="#basic-factories">Basic Factories</a></li>
<li><a class="reference internal" href="#factories-extensions">Factories &amp; Extensions</a></li>
<li><a class="reference internal" href="#using-applications">Using Applications</a></li>
<li><a class="reference internal" href="#factory-improvements">Factory Improvements</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="packages.html" title="previous chapter">Large Applications as Packages</a>
<li>Next: <a href="appdispatch.html" title="next chapter">Application Dispatching</a></ul>
<li>Previous: <a href="streaming.html" title="previous chapter">Streaming Contents</a>
<li>Next: <a href="methodoverrides.html" title="next chapter">Adding HTTP Method Overrides</a></ul>
</li>
</ul>
</li>
@ -210,4 +131,4 @@ hooking in before/after request handlers etc.)</p></li>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Caching &#8212; Flask Documentation (3.2.x)</title>
<title>Adding a favicon &#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="View Decorators" href="viewdecorators.html" />
<link rel="prev" title="Uploading Files" href="fileuploads.html" />
<link rel="next" title="Streaming Contents" href="streaming.html" />
<link rel="prev" title="MongoDB with MongoEngine" href="mongoengine.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,33 +28,73 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="viewdecorators.html" title="View Decorators"
<a href="streaming.html" title="Streaming Contents"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="fileuploads.html" title="Uploading Files"
<a href="mongoengine.html" title="MongoDB with MongoEngine"
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="">Caching</a></li>
<li class="nav-item nav-item-this"><a href="">Adding a favicon</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="caching">
<h1>Caching<a class="headerlink" href="#caching" title="Link to this heading"></a></h1>
<p>When your application runs slow, throw some caches in. Well, at least
its the easiest way to speed up things. What does a cache do? Say you
have a function that takes some time to complete but the results would
still be good enough if they were 5 minutes old. So then the idea is that
you actually put the result of that calculation into a cache for some
time.</p>
<p>Flask itself does not provide caching for you, but <a class="reference external" href="https://flask-caching.readthedocs.io/en/latest/">Flask-Caching</a>, an
extension for Flask does. Flask-Caching supports various backends, and it is
even possible to develop your own caching backend.</p>
<section id="adding-a-favicon">
<h1>Adding a favicon<a class="headerlink" href="#adding-a-favicon" title="Link to this heading"></a></h1>
<p>A “favicon” is an icon used by browsers for tabs and bookmarks. This helps
to distinguish your website and to give it a unique brand.</p>
<p>A common question is how to add a favicon to a Flask application. First, of
course, you need an icon. It should be 16 × 16 pixels and in the ICO file
format. This is not a requirement but a de-facto standard supported by all
relevant browsers. Put the icon in your static directory as
<code class="file docutils literal notranslate"><span class="pre">favicon.ico</span></code>.</p>
<p>Now, to get browsers to find your icon, the correct way is to add a link
tag in your HTML. So, for example:</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&quot;shortcut icon&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;favicon.ico&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>Thats all you need for most browsers, however some really old ones do not
support this standard. The old de-facto standard is to serve this file,
with this name, at the website root. If your application is not mounted at
the root path of the domain you either need to configure the web server to
serve the icon at the root or if you cant do that youre out of luck. If
however your application is the root you can simply route a redirect:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span>
<span class="s2">&quot;/favicon.ico&quot;</span><span class="p">,</span>
<span class="n">endpoint</span><span class="o">=</span><span class="s2">&quot;favicon&quot;</span><span class="p">,</span>
<span class="n">redirect_to</span><span class="o">=</span><span class="n">url_for</span><span class="p">(</span><span class="s2">&quot;static&quot;</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="s2">&quot;favicon.ico&quot;</span><span class="p">),</span>
<span class="p">)</span>
</pre></div>
</div>
<p>If you want to save the extra redirect request you can also write a view
using <a class="reference internal" href="../api.html#flask.send_from_directory" title="flask.send_from_directory"><code class="xref py py-func docutils literal notranslate"><span class="pre">send_from_directory()</span></code></a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">os</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">send_from_directory</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/favicon.ico&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">favicon</span><span class="p">():</span>
<span class="k">return</span> <span class="n">send_from_directory</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">root_path</span><span class="p">,</span> <span class="s1">&#39;static&#39;</span><span class="p">),</span>
<span class="s1">&#39;favicon.ico&#39;</span><span class="p">,</span> <span class="n">mimetype</span><span class="o">=</span><span class="s1">&#39;image/vnd.microsoft.icon&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>We can leave out the explicit mimetype and it will be guessed, but we may
as well specify it to avoid the extra guessing, as it will always be the
same.</p>
<p>The above will serve the icon via your application and if possible its
better to configure your dedicated web server to serve it; refer to the
web servers documentation.</p>
<section id="see-also">
<h2>See also<a class="headerlink" href="#see-also" title="Link to this heading"></a></h2>
<ul class="simple">
<li><p>The <a class="reference external" href="https://en.wikipedia.org/wiki/Favicon">Favicon</a> article on
Wikipedia</p></li>
</ul>
</section>
</section>
@ -65,20 +105,28 @@ even possible to develop your own caching backend.</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"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Adding a favicon</a><ul>
<li><a class="reference internal" href="#see-also">See also</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="fileuploads.html" title="previous chapter">Uploading Files</a>
<li>Next: <a href="viewdecorators.html" title="next chapter">View Decorators</a></ul>
<li>Previous: <a href="mongoengine.html" title="previous chapter">MongoDB with MongoEngine</a>
<li>Next: <a href="streaming.html" title="next chapter">Streaming Contents</a></ul>
</li>
</ul>
</li>
@ -102,4 +150,4 @@ even possible to develop your own caching backend.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Background Tasks with Celery &#8212; Flask Documentation (3.2.x)</title>
<title>Uploading Files &#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="Subclassing Flask" href="subclassing.html" />
<link rel="prev" title="Request Content Checksums" href="requestchecksum.html" />
<link rel="next" title="Caching" href="caching.html" />
<link rel="prev" title="SQLAlchemy in Flask" href="sqlalchemy.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,214 +28,189 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="subclassing.html" title="Subclassing Flask"
<a href="caching.html" title="Caching"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="requestchecksum.html" title="Request Content Checksums"
<a href="sqlalchemy.html" title="SQLAlchemy in Flask"
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="">Background Tasks with Celery</a></li>
<li class="nav-item nav-item-this"><a href="">Uploading Files</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="background-tasks-with-celery">
<h1>Background Tasks with Celery<a class="headerlink" href="#background-tasks-with-celery" title="Link to this heading"></a></h1>
<p>If your application has a long running task, such as processing some uploaded data or
sending email, you dont want to wait for it to finish during a request. Instead, use a
task queue to send the necessary data to another process that will run the task in the
background while the request returns immediately.</p>
<p><a class="reference external" href="https://celery.readthedocs.io">Celery</a> is a powerful task queue that can be used for simple background tasks as well
as complex multi-stage programs and schedules. This guide will show you how to configure
Celery using Flask. Read Celerys <a class="reference external" href="https://celery.readthedocs.io/en/latest/getting-started/first-steps-with-celery.html">First Steps with Celery</a> guide to learn how to use
Celery itself.</p>
<p>The Flask repository contains <a class="reference external" href="https://github.com/pallets/flask/tree/main/examples/celery">an example</a>
based on the information on this page, which also shows how to use JavaScript to submit
tasks and poll for progress and results.</p>
<section id="install">
<h2>Install<a class="headerlink" href="#install" title="Link to this heading"></a></h2>
<p>Install Celery from PyPI, for example using pip:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ pip install celery
</pre></div>
</div>
</section>
<section id="integrate-celery-with-flask">
<h2>Integrate Celery with Flask<a class="headerlink" href="#integrate-celery-with-flask" title="Link to this heading"></a></h2>
<p>You can use Celery without any integration with Flask, but its convenient to configure
it through Flasks config, and to let tasks access the Flask application.</p>
<p>Celery uses similar ideas to Flask, with a <code class="docutils literal notranslate"><span class="pre">Celery</span></code> app object that has configuration
and registers tasks. While creating a Flask app, use the following code to create and
configure a Celery app as well.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">celery</span><span class="w"> </span><span class="kn">import</span> <span class="n">Celery</span><span class="p">,</span> <span class="n">Task</span>
<span class="k">def</span><span class="w"> </span><span class="nf">celery_init_app</span><span class="p">(</span><span class="n">app</span><span class="p">:</span> <span class="n">Flask</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Celery</span><span class="p">:</span>
<span class="k">class</span><span class="w"> </span><span class="nc">FlaskTask</span><span class="p">(</span><span class="n">Task</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="nb">object</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="nb">object</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">object</span><span class="p">:</span>
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">app_context</span><span class="p">():</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<section id="uploading-files">
<h1>Uploading Files<a class="headerlink" href="#uploading-files" title="Link to this heading"></a></h1>
<p>Ah yes, the good old problem of file uploads. The basic idea of file
uploads is actually quite simple. It basically works like this:</p>
<ol class="arabic simple">
<li><p>A <code class="docutils literal notranslate"><span class="pre">&lt;form&gt;</span></code> tag is marked with <code class="docutils literal notranslate"><span class="pre">enctype=multipart/form-data</span></code>
and an <code class="docutils literal notranslate"><span class="pre">&lt;input</span> <span class="pre">type=file&gt;</span></code> is placed in that form.</p></li>
<li><p>The application accesses the file from the <code class="xref py py-attr docutils literal notranslate"><span class="pre">files</span></code>
dictionary on the request object.</p></li>
<li><p>use the <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/datastructures/#werkzeug.datastructures.FileStorage.save" title="(in Werkzeug v3.1.x)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">save()</span></code></a> method of the file to save
the file permanently somewhere on the filesystem.</p></li>
</ol>
<section id="a-gentle-introduction">
<h2>A Gentle Introduction<a class="headerlink" href="#a-gentle-introduction" title="Link to this heading"></a></h2>
<p>Lets start with a very basic application that uploads a file to a
specific upload folder and displays a file to the user. Lets look at the
bootstrapping code for our application:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">os</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">flash</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">redirect</span><span class="p">,</span> <span class="n">url_for</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">werkzeug.utils</span><span class="w"> </span><span class="kn">import</span> <span class="n">secure_filename</span>
<span class="n">celery_app</span> <span class="o">=</span> <span class="n">Celery</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">task_cls</span><span class="o">=</span><span class="n">FlaskTask</span><span class="p">)</span>
<span class="n">celery_app</span><span class="o">.</span><span class="n">config_from_object</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;CELERY&quot;</span><span class="p">])</span>
<span class="n">celery_app</span><span class="o">.</span><span class="n">set_default</span><span class="p">()</span>
<span class="n">app</span><span class="o">.</span><span class="n">extensions</span><span class="p">[</span><span class="s2">&quot;celery&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">celery_app</span>
<span class="k">return</span> <span class="n">celery_app</span>
</pre></div>
</div>
<p>This creates and returns a <code class="docutils literal notranslate"><span class="pre">Celery</span></code> app object. Celery <a class="reference external" href="https://celery.readthedocs.io/en/stable/userguide/configuration.html">configuration</a> is taken from
the <code class="docutils literal notranslate"><span class="pre">CELERY</span></code> key in the Flask configuration. The Celery app is set as the default, so
that it is seen during each request. The <code class="docutils literal notranslate"><span class="pre">Task</span></code> subclass automatically runs task
functions with a Flask app context active, so that services like your database
connections are available.</p>
<p>Heres a basic <code class="docutils literal notranslate"><span class="pre">example.py</span></code> that configures Celery to use Redis for communication. We
enable a result backend, but ignore results by default. This allows us to store results
only for tasks where we care about the result.</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="n">UPLOAD_FOLDER</span> <span class="o">=</span> <span class="s1">&#39;/path/to/the/uploads&#39;</span>
<span class="n">ALLOWED_EXTENSIONS</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;txt&#39;</span><span class="p">,</span> <span class="s1">&#39;pdf&#39;</span><span class="p">,</span> <span class="s1">&#39;png&#39;</span><span class="p">,</span> <span class="s1">&#39;jpg&#39;</span><span class="p">,</span> <span class="s1">&#39;jpeg&#39;</span><span class="p">,</span> <span class="s1">&#39;gif&#39;</span><span class="p">}</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="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_mapping</span><span class="p">(</span>
<span class="n">CELERY</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span>
<span class="n">broker_url</span><span class="o">=</span><span class="s2">&quot;redis://localhost&quot;</span><span class="p">,</span>
<span class="n">result_backend</span><span class="o">=</span><span class="s2">&quot;redis://localhost&quot;</span><span class="p">,</span>
<span class="n">task_ignore_result</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="p">),</span>
<span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;UPLOAD_FOLDER&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">UPLOAD_FOLDER</span>
</pre></div>
</div>
<p>So first we need a couple of imports. Most should be straightforward, the
<code class="xref py py-func docutils literal notranslate"><span class="pre">werkzeug.secure_filename()</span></code> is explained a little bit later. The
<code class="docutils literal notranslate"><span class="pre">UPLOAD_FOLDER</span></code> is where we will store the uploaded files and the
<code class="docutils literal notranslate"><span class="pre">ALLOWED_EXTENSIONS</span></code> is the set of allowed file extensions.</p>
<p>Why do we limit the extensions that are allowed? You probably dont want
your users to be able to upload everything there if the server is directly
sending out the data to the client. That way you can make sure that users
are not able to upload HTML files that would cause XSS problems (see
<a class="reference internal" href="../web-security.html#security-xss"><span class="std std-ref">Cross-Site Scripting (XSS)</span></a>). Also make sure to disallow <code class="docutils literal notranslate"><span class="pre">.php</span></code> files if the server
executes them, but who has PHP installed on their server, right? :)</p>
<p>Next the functions that check if an extension is valid and that uploads
the file and redirects the user to the URL for the uploaded file:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">allowed_file</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
<span class="k">return</span> <span class="s1">&#39;.&#39;</span> <span class="ow">in</span> <span class="n">filename</span> <span class="ow">and</span> \
<span class="n">filename</span><span class="o">.</span><span class="n">rsplit</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="n">ALLOWED_EXTENSIONS</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="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">upload_file</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="p">:</span>
<span class="c1"># check if the post request has the file part</span>
<span class="k">if</span> <span class="s1">&#39;file&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">request</span><span class="o">.</span><span class="n">files</span><span class="p">:</span>
<span class="n">flash</span><span class="p">(</span><span class="s1">&#39;No file part&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">url</span><span class="p">)</span>
<span class="n">file</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">files</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">]</span>
<span class="c1"># If the user does not select a file, the browser submits an</span>
<span class="c1"># empty file without a filename.</span>
<span class="k">if</span> <span class="n">file</span><span class="o">.</span><span class="n">filename</span> <span class="o">==</span> <span class="s1">&#39;&#39;</span><span class="p">:</span>
<span class="n">flash</span><span class="p">(</span><span class="s1">&#39;No selected file&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">url</span><span class="p">)</span>
<span class="k">if</span> <span class="n">file</span> <span class="ow">and</span> <span class="n">allowed_file</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">filename</span><span class="p">):</span>
<span class="n">filename</span> <span class="o">=</span> <span class="n">secure_filename</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>
<span class="n">file</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;UPLOAD_FOLDER&#39;</span><span class="p">],</span> <span class="n">filename</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;download_file&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">filename</span><span class="p">))</span>
<span class="k">return</span> <span class="s1">&#39;&#39;&#39;</span>
<span class="s1"> &lt;!doctype html&gt;</span>
<span class="s1"> &lt;title&gt;Upload new File&lt;/title&gt;</span>
<span class="s1"> &lt;h1&gt;Upload new File&lt;/h1&gt;</span>
<span class="s1"> &lt;form method=post enctype=multipart/form-data&gt;</span>
<span class="s1"> &lt;input type=file name=file&gt;</span>
<span class="s1"> &lt;input type=submit value=Upload&gt;</span>
<span class="s1"> &lt;/form&gt;</span>
<span class="s1"> &#39;&#39;&#39;</span>
</pre></div>
</div>
<p>So what does that <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/utils/#werkzeug.utils.secure_filename" title="(in Werkzeug v3.1.x)"><code class="xref py py-func docutils literal notranslate"><span class="pre">secure_filename()</span></code></a> function actually do?
Now the problem is that there is that principle called “never trust user
input”. This is also true for the filename of an uploaded file. All
submitted form data can be forged, and filenames can be dangerous. For
the moment just remember: always use that function to secure a filename
before storing it directly on the filesystem.</p>
<div class="admonition-information-for-the-pros admonition">
<p class="admonition-title">Information for the Pros</p>
<p>So youre interested in what that <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/utils/#werkzeug.utils.secure_filename" title="(in Werkzeug v3.1.x)"><code class="xref py py-func docutils literal notranslate"><span class="pre">secure_filename()</span></code></a>
function does and what the problem is if youre not using it? So just
imagine someone would send the following information as <code class="code docutils literal notranslate"><span class="pre">filename</span></code> to
your application:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">filename</span> <span class="o">=</span> <span class="s2">&quot;../../../../home/username/.bashrc&quot;</span>
</pre></div>
</div>
<p>Assuming the number of <code class="docutils literal notranslate"><span class="pre">../</span></code> is correct and you would join this with
the <code class="docutils literal notranslate"><span class="pre">UPLOAD_FOLDER</span></code> the user might have the ability to modify a file on
the servers filesystem he or she should not modify. This does require some
knowledge about how the application looks like, but trust me, hackers
are patient :)</p>
<p>Now lets look how that function works:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">secure_filename</span><span class="p">(</span><span class="s1">&#39;../../../../home/username/.bashrc&#39;</span><span class="p">)</span>
<span class="go">&#39;home_username_.bashrc&#39;</span>
</pre></div>
</div>
</div>
<p>We want to be able to serve the uploaded files so they can be downloaded
by users. Well define a <code class="docutils literal notranslate"><span class="pre">download_file</span></code> view to serve files in the
upload folder by name. <code class="docutils literal notranslate"><span class="pre">url_for(&quot;download_file&quot;,</span> <span class="pre">name=name)</span></code> generates
download URLs.</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">send_from_directory</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/uploads/&lt;name&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">download_file</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
<span class="k">return</span> <span class="n">send_from_directory</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;UPLOAD_FOLDER&quot;</span><span class="p">],</span> <span class="n">name</span><span class="p">)</span>
</pre></div>
</div>
<p>If youre using middleware or the HTTP server to serve files, you can
register the <code class="docutils literal notranslate"><span class="pre">download_file</span></code> endpoint as <code class="docutils literal notranslate"><span class="pre">build_only</span></code> so <code class="docutils literal notranslate"><span class="pre">url_for</span></code>
will work without a view function.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span>
<span class="s2">&quot;/uploads/&lt;name&gt;&quot;</span><span class="p">,</span> <span class="n">endpoint</span><span class="o">=</span><span class="s2">&quot;download_file&quot;</span><span class="p">,</span> <span class="n">build_only</span><span class="o">=</span><span class="kc">True</span>
<span class="p">)</span>
<span class="n">celery_app</span> <span class="o">=</span> <span class="n">celery_init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
</pre></div>
</div>
<p>Point the <code class="docutils literal notranslate"><span class="pre">celery</span> <span class="pre">worker</span></code> command at this and it will find the <code class="docutils literal notranslate"><span class="pre">celery_app</span></code> object.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ celery -A example worker --loglevel INFO
</pre></div>
</div>
<p>You can also run the <code class="docutils literal notranslate"><span class="pre">celery</span> <span class="pre">beat</span></code> command to run tasks on a schedule. See Celerys
docs for more information about defining schedules.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ celery -A example beat --loglevel INFO
</pre></div>
</div>
</section>
<section id="application-factory">
<h2>Application Factory<a class="headerlink" href="#application-factory" title="Link to this heading"></a></h2>
<p>When using the Flask application factory pattern, call the <code class="docutils literal notranslate"><span class="pre">celery_init_app</span></code> function
inside the factory. It sets <code class="docutils literal notranslate"><span class="pre">app.extensions[&quot;celery&quot;]</span></code> to the Celery app object, which
can be used to get the Celery app from the Flask app returned by the factory.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">create_app</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Flask</span><span class="p">:</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="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_mapping</span><span class="p">(</span>
<span class="n">CELERY</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span>
<span class="n">broker_url</span><span class="o">=</span><span class="s2">&quot;redis://localhost&quot;</span><span class="p">,</span>
<span class="n">result_backend</span><span class="o">=</span><span class="s2">&quot;redis://localhost&quot;</span><span class="p">,</span>
<span class="n">task_ignore_result</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="p">),</span>
<span class="p">)</span>
<span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">from_prefixed_env</span><span class="p">()</span>
<span class="n">celery_init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<span class="k">return</span> <span class="n">app</span>
</pre></div>
<section id="improving-uploads">
<h2>Improving Uploads<a class="headerlink" href="#improving-uploads" title="Link to this heading"></a></h2>
<details class="changelog">
<summary>Changelog</summary><div class="versionadded">
<p><span class="versionmodified added">Added in version 0.6.</span></p>
</div>
<p>To use <code class="docutils literal notranslate"><span class="pre">celery</span></code> commands, Celery needs an app object, but thats no longer directly
available. Create a <code class="docutils literal notranslate"><span class="pre">make_celery.py</span></code> file that calls the Flask app factory and gets
the Celery app from the returned Flask app.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">example</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_app</span>
</details><p>So how exactly does Flask handle uploads? Well it will store them in the
webservers memory if the files are reasonably small, otherwise in a
temporary location (as returned by <a class="reference external" href="https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir" title="(in Python v3.13)"><code class="xref py py-func docutils literal notranslate"><span class="pre">tempfile.gettempdir()</span></code></a>). But how
do you specify the maximum file size after which an upload is aborted? By
default Flask will happily accept file uploads with an unlimited amount of
memory, but you can limit that by setting the <code class="docutils literal notranslate"><span class="pre">MAX_CONTENT_LENGTH</span></code>
config key:</p>
<div class="highlight-default 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">flask_app</span> <span class="o">=</span> <span class="n">create_app</span><span class="p">()</span>
<span class="n">celery_app</span> <span class="o">=</span> <span class="n">flask_app</span><span class="o">.</span><span class="n">extensions</span><span class="p">[</span><span class="s2">&quot;celery&quot;</span><span class="p">]</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="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;MAX_CONTENT_LENGTH&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">1000</span> <span class="o">*</span> <span class="mi">1000</span>
</pre></div>
</div>
<p>Point the <code class="docutils literal notranslate"><span class="pre">celery</span></code> command to this file.</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ celery -A make_celery worker --loglevel INFO
$ celery -A make_celery beat --loglevel INFO
</pre></div>
<p>The code above will limit the maximum allowed payload to 16 megabytes.
If a larger file is transmitted, Flask will raise a
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.RequestEntityTooLarge" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RequestEntityTooLarge</span></code></a> exception.</p>
<div class="admonition-connection-reset-issue admonition">
<p class="admonition-title">Connection Reset Issue</p>
<p>When using the local development server, you may get a connection
reset error instead of a 413 response. You will get the correct
status response when running the app with a production WSGI server.</p>
</div>
<p>This feature was added in Flask 0.6 but can be achieved in older versions
as well by subclassing the request object. For more information on that
consult the Werkzeug documentation on file handling.</p>
</section>
<section id="defining-tasks">
<h2>Defining Tasks<a class="headerlink" href="#defining-tasks" title="Link to this heading"></a></h2>
<p>Using <code class="docutils literal notranslate"><span class="pre">&#64;celery_app.task</span></code> to decorate task functions requires access to the
<code class="docutils literal notranslate"><span class="pre">celery_app</span></code> object, which wont be available when using the factory pattern. It also
means that the decorated tasks are tied to the specific Flask and Celery app instances,
which could be an issue during testing if you change configuration for a test.</p>
<p>Instead, use Celerys <code class="docutils literal notranslate"><span class="pre">&#64;shared_task</span></code> decorator. This creates task objects that will
access whatever the “current app” is, which is a similar concept to Flasks blueprints
and app context. This is why we called <code class="docutils literal notranslate"><span class="pre">celery_app.set_default()</span></code> above.</p>
<p>Heres an example task that adds two numbers together and returns the result.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">celery</span><span class="w"> </span><span class="kn">import</span> <span class="n">shared_task</span>
<span class="nd">@shared_task</span><span class="p">(</span><span class="n">ignore_result</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">add_together</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
<span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
</pre></div>
</div>
<p>Earlier, we configured Celery to ignore task results by default. Since we want to know
the return value of this task, we set <code class="docutils literal notranslate"><span class="pre">ignore_result=False</span></code>. On the other hand, a task
that didnt need a result, such as sending an email, wouldnt set this.</p>
<section id="upload-progress-bars">
<h2>Upload Progress Bars<a class="headerlink" href="#upload-progress-bars" title="Link to this heading"></a></h2>
<p>A while ago many developers had the idea to read the incoming file in
small chunks and store the upload progress in the database to be able to
poll the progress with JavaScript from the client. The client asks the
server every 5 seconds how much it has transmitted, but this is
something it should already know.</p>
</section>
<section id="calling-tasks">
<h2>Calling Tasks<a class="headerlink" href="#calling-tasks" title="Link to this heading"></a></h2>
<p>The decorated function becomes a task object with methods to call it in the background.
The simplest way is to use the <code class="docutils literal notranslate"><span class="pre">delay(*args,</span> <span class="pre">**kwargs)</span></code> method. See Celerys docs for
more methods.</p>
<p>A Celery worker must be running to run the task. Starting a worker is shown in the
previous sections.</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">request</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">&quot;/add&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">start_add</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">object</span><span class="p">]:</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;a&quot;</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;b&quot;</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">add_together</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
<span class="k">return</span> <span class="p">{</span><span class="s2">&quot;result_id&quot;</span><span class="p">:</span> <span class="n">result</span><span class="o">.</span><span class="n">id</span><span class="p">}</span>
</pre></div>
</div>
<p>The route doesnt get the tasks result immediately. That would defeat the purpose by
blocking the response. Instead, we return the running tasks result id, which we can use
later to get the result.</p>
</section>
<section id="getting-results">
<h2>Getting Results<a class="headerlink" href="#getting-results" title="Link to this heading"></a></h2>
<p>To fetch the result of the task we started above, well add another route that takes the
result id we returned before. We return whether the task is finished (ready), whether it
finished successfully, and what the return value (or error) was if it is finished.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">celery.result</span><span class="w"> </span><span class="kn">import</span> <span class="n">AsyncResult</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/result/&lt;id&gt;&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">task_result</span><span class="p">(</span><span class="nb">id</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="nb">object</span><span class="p">]:</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">AsyncResult</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span>
<span class="k">return</span> <span class="p">{</span>
<span class="s2">&quot;ready&quot;</span><span class="p">:</span> <span class="n">result</span><span class="o">.</span><span class="n">ready</span><span class="p">(),</span>
<span class="s2">&quot;successful&quot;</span><span class="p">:</span> <span class="n">result</span><span class="o">.</span><span class="n">successful</span><span class="p">(),</span>
<span class="s2">&quot;value&quot;</span><span class="p">:</span> <span class="n">result</span><span class="o">.</span><span class="n">result</span> <span class="k">if</span> <span class="n">result</span><span class="o">.</span><span class="n">ready</span><span class="p">()</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Now you can start the task using the first route, then poll for the result using the
second route. This keeps the Flask request workers from being blocked waiting for tasks
to finish.</p>
<p>The Flask repository contains <a class="reference external" href="https://github.com/pallets/flask/tree/main/examples/celery">an example</a>
using JavaScript to submit tasks and poll for progress and results.</p>
</section>
<section id="passing-data-to-tasks">
<h2>Passing Data to Tasks<a class="headerlink" href="#passing-data-to-tasks" title="Link to this heading"></a></h2>
<p>The “add” task above took two integers as arguments. To pass arguments to tasks, Celery
has to serialize them to a format that it can pass to other processes. Therefore,
passing complex objects is not recommended. For example, it would be impossible to pass
a SQLAlchemy model object, since that object is probably not serializable and is tied to
the session that queried it.</p>
<p>Pass the minimal amount of data necessary to fetch or recreate any complex data within
the task. Consider a task that will run when the logged in user asks for an archive of
their data. The Flask request knows the logged in user, and has the user object queried
from the database. It got that by querying the database for a given id, so the task can
do the same thing. Pass the users id rather than the user object.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@shared_task</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate_user_archive</span><span class="p">(</span><span class="n">user_id</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">user_id</span><span class="p">)</span>
<span class="o">...</span>
<span class="n">generate_user_archive</span><span class="o">.</span><span class="n">delay</span><span class="p">(</span><span class="n">current_user</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
</pre></div>
</div>
<section id="an-easier-solution">
<h2>An Easier Solution<a class="headerlink" href="#an-easier-solution" title="Link to this heading"></a></h2>
<p>Now there are better solutions that work faster and are more reliable. There
are JavaScript libraries like <a class="reference external" href="https://jquery.com/">jQuery</a> that have form plugins to ease the
construction of progress bar.</p>
<p>Because the common pattern for file uploads exists almost unchanged in all
applications dealing with uploads, there are also some Flask extensions that
implement a full fledged upload mechanism that allows controlling which
file extensions are allowed to be uploaded.</p>
</section>
</section>
@ -247,23 +222,20 @@ do the same thing. Pass the users id rather than the user object.</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"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Background Tasks with Celery</a><ul>
<li><a class="reference internal" href="#install">Install</a></li>
<li><a class="reference internal" href="#integrate-celery-with-flask">Integrate Celery with Flask</a></li>
<li><a class="reference internal" href="#application-factory">Application Factory</a></li>
<li><a class="reference internal" href="#defining-tasks">Defining Tasks</a></li>
<li><a class="reference internal" href="#calling-tasks">Calling Tasks</a></li>
<li><a class="reference internal" href="#getting-results">Getting Results</a></li>
<li><a class="reference internal" href="#passing-data-to-tasks">Passing Data to Tasks</a></li>
<li><a class="reference internal" href="#">Uploading Files</a><ul>
<li><a class="reference internal" href="#a-gentle-introduction">A Gentle Introduction</a></li>
<li><a class="reference internal" href="#improving-uploads">Improving Uploads</a></li>
<li><a class="reference internal" href="#upload-progress-bars">Upload Progress Bars</a></li>
<li><a class="reference internal" href="#an-easier-solution">An Easier Solution</a></li>
</ul>
</li>
</ul>
@ -273,8 +245,8 @@ do the same thing. Pass the users id rather than the user object.</p>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="requestchecksum.html" title="previous chapter">Request Content Checksums</a>
<li>Next: <a href="subclassing.html" title="next chapter">Subclassing Flask</a></ul>
<li>Previous: <a href="sqlalchemy.html" title="previous chapter">SQLAlchemy in Flask</a>
<li>Next: <a href="caching.html" title="next chapter">Caching</a></ul>
</li>
</ul>
</li>
@ -298,4 +270,4 @@ do the same thing. Pass the users id rather than the user object.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Deferred Request Callbacks &#8212; Flask Documentation (3.2.x)</title>
<title>Message Flashing &#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="Adding HTTP Method Overrides" href="methodoverrides.html" />
<link rel="prev" title="Streaming Contents" href="streaming.html" />
<link rel="next" title="JavaScript, fetch, and JSON" href="javascript.html" />
<link rel="prev" title="Template Inheritance" href="templateinheritance.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,62 +28,161 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="methodoverrides.html" title="Adding HTTP Method Overrides"
<a href="javascript.html" title="JavaScript, fetch, and JSON"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="streaming.html" title="Streaming Contents"
<a href="templateinheritance.html" title="Template Inheritance"
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="">Deferred Request Callbacks</a></li>
<li class="nav-item nav-item-this"><a href="">Message Flashing</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="deferred-request-callbacks">
<h1>Deferred Request Callbacks<a class="headerlink" href="#deferred-request-callbacks" title="Link to this heading"></a></h1>
<p>One of the design principles of Flask is that response objects are created and
passed down a chain of potential callbacks that can modify them or replace
them. When the request handling starts, there is no response object yet. It is
created as necessary either by a view function or by some other component in
the system.</p>
<p>What happens if you want to modify the response at a point where the response
does not exist yet? A common example for that would be a
<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> callback that wants to set a cookie on the
response object.</p>
<p>One way is to avoid the situation. Very often that is possible. For instance
you can try to move that logic into a <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>
callback instead. However, sometimes moving code there makes it
more complicated or awkward to reason about.</p>
<p>As an alternative, you can use <a class="reference internal" href="../api.html#flask.after_this_request" title="flask.after_this_request"><code class="xref py py-func docutils literal notranslate"><span class="pre">after_this_request()</span></code></a> to register
callbacks that will execute after only the current request. This way you can
defer code execution from anywhere in the application, based on the current
request.</p>
<p>At any time during a request, we can register a function to be called at the
end of the request. For example you can remember the current language of the
user in a cookie in a <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> callback:</p>
<div class="highlight-default 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">request</span><span class="p">,</span> <span class="n">after_this_request</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">before_request</span>
<span class="k">def</span><span class="w"> </span><span class="nf">detect_user_language</span><span class="p">():</span>
<span class="n">language</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">cookies</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;user_lang&#39;</span><span class="p">)</span>
<section id="message-flashing">
<h1>Message Flashing<a class="headerlink" href="#message-flashing" title="Link to this heading"></a></h1>
<p>Good applications and user interfaces are all about feedback. If the user
does not get enough feedback they will probably end up hating the
application. Flask provides a really simple way to give feedback to a
user with the flashing system. The flashing system basically makes it
possible to record a message at the end of a request and access it next
request and only next request. This is usually combined with a layout
template that does this. Note that browsers and sometimes web servers enforce
a limit on cookie sizes. This means that flashing messages that are too
large for session cookies causes message flashing to fail silently.</p>
<section id="simple-flashing">
<h2>Simple Flashing<a class="headerlink" href="#simple-flashing" title="Link to this heading"></a></h2>
<p>So here is a full example:</p>
<div class="highlight-default 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">flash</span><span class="p">,</span> <span class="n">redirect</span><span class="p">,</span> <span class="n">render_template</span><span class="p">,</span> \
<span class="n">request</span><span class="p">,</span> <span class="n">url_for</span>
<span class="k">if</span> <span class="n">language</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">language</span> <span class="o">=</span> <span class="n">guess_language_from_request</span><span class="p">()</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="n">app</span><span class="o">.</span><span class="n">secret_key</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">&#39;_5#y2L&quot;F4Q8z</span><span class="se">\n\xec</span><span class="s1">]/&#39;</span>
<span class="c1"># when the response exists, set a cookie with the language</span>
<span class="nd">@after_this_request</span>
<span class="k">def</span><span class="w"> </span><span class="nf">remember_language</span><span class="p">(</span><span class="n">response</span><span class="p">):</span>
<span class="n">response</span><span class="o">.</span><span class="n">set_cookie</span><span class="p">(</span><span class="s1">&#39;user_lang&#39;</span><span class="p">,</span> <span class="n">language</span><span class="p">)</span>
<span class="k">return</span> <span class="n">response</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">index</span><span class="p">():</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">&#39;index.html&#39;</span><span class="p">)</span>
<span class="n">g</span><span class="o">.</span><span class="n">language</span> <span class="o">=</span> <span class="n">language</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/login&#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">login</span><span class="p">():</span>
<span class="n">error</span> <span class="o">=</span> <span class="kc">None</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="p">:</span>
<span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="p">[</span><span class="s1">&#39;username&#39;</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">&#39;admin&#39;</span> <span class="ow">or</span> \
<span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="p">[</span><span class="s1">&#39;password&#39;</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">&#39;secret&#39;</span><span class="p">:</span>
<span class="n">error</span> <span class="o">=</span> <span class="s1">&#39;Invalid credentials&#39;</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">flash</span><span class="p">(</span><span class="s1">&#39;You were successfully logged in&#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;index&#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;login.html&#39;</span><span class="p">,</span> <span class="n">error</span><span class="o">=</span><span class="n">error</span><span class="p">)</span>
</pre></div>
</div>
<p>And here is the <code class="file docutils literal notranslate"><span class="pre">layout.html</span></code> template which does the magic:</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">title</span><span class="p">&gt;</span>My Application<span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">with</span> <span class="nv">messages</span> <span class="o">=</span> <span class="nv">get_flashed_messages</span><span class="o">()</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">messages</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">flashes</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">message</span> <span class="k">in</span> <span class="nv">messages</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">message</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="cp">{%</span> <span class="k">endwith</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">body</span> <span class="cp">%}{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>Here is the <code class="file docutils literal notranslate"><span class="pre">index.html</span></code> template which inherits from <code class="file docutils literal notranslate"><span class="pre">layout.html</span></code>:</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">body</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>Overview<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="p">&gt;</span>Do you want to <span class="p">&lt;</span><span class="nt">a</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;login&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>log in?<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>
</pre></div>
</div>
<p>And here is the <code class="file docutils literal notranslate"><span class="pre">login.html</span></code> template which also inherits from
<code class="file docutils literal notranslate"><span class="pre">layout.html</span></code>:</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">body</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>Login<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">error</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">p</span> <span class="na">class</span><span class="o">=</span><span class="s">error</span><span class="p">&gt;&lt;</span><span class="nt">strong</span><span class="p">&gt;</span>Error:<span class="p">&lt;/</span><span class="nt">strong</span><span class="p">&gt;</span> <span class="cp">{{</span> <span class="nv">error</span> <span class="cp">}}</span>
<span class="cp">{%</span> <span class="k">endif</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="p">&lt;</span><span class="nt">dt</span><span class="p">&gt;</span>Username:
<span class="p">&lt;</span><span class="nt">dd</span><span class="p">&gt;&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">text</span> <span class="na">name</span><span class="o">=</span><span class="s">username</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span>
<span class="nv">request.form.username</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">dt</span><span class="p">&gt;</span>Password:
<span class="p">&lt;</span><span class="nt">dd</span><span class="p">&gt;&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">password</span> <span class="na">name</span><span class="o">=</span><span class="s">password</span><span class="p">&gt;</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">Login</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div>
</div>
</section>
<section id="flashing-with-categories">
<h2>Flashing With Categories<a class="headerlink" href="#flashing-with-categories" title="Link to this heading"></a></h2>
<details class="changelog">
<summary>Changelog</summary><div class="versionadded">
<p><span class="versionmodified added">Added in version 0.3.</span></p>
</div>
</details><p>It is also possible to provide categories when flashing a message. The
default category if nothing is provided is <code class="docutils literal notranslate"><span class="pre">'message'</span></code>. Alternative
categories can be used to give the user better feedback. For example
error messages could be displayed with a red background.</p>
<p>To flash a message with a different category, just use the second argument
to the <a class="reference internal" href="../api.html#flask.flash" title="flask.flash"><code class="xref py py-func docutils literal notranslate"><span class="pre">flash()</span></code></a> function:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">flash</span><span class="p">(</span><span class="s1">&#39;Invalid password provided&#39;</span><span class="p">,</span> <span class="s1">&#39;error&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Inside the template you then have to tell the
<a class="reference internal" href="../api.html#flask.get_flashed_messages" title="flask.get_flashed_messages"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_flashed_messages()</span></code></a> function to also return the
categories. The loop looks slightly different in that situation then:</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">with</span> <span class="nv">messages</span> <span class="o">=</span> <span class="nv">get_flashed_messages</span><span class="o">(</span><span class="nv">with_categories</span><span class="o">=</span><span class="kp">true</span><span class="o">)</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">messages</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">flashes</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">category</span><span class="o">,</span> <span class="nv">message</span> <span class="k">in</span> <span class="nv">messages</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">li</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">category</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">message</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="cp">{%</span> <span class="k">endwith</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>This is just one example of how to render these flashed messages. One
might also use the category to add a prefix such as
<code class="docutils literal notranslate"><span class="pre">&lt;strong&gt;Error:&lt;/strong&gt;</span></code> to the message.</p>
</section>
<section id="filtering-flash-messages">
<h2>Filtering Flash Messages<a class="headerlink" href="#filtering-flash-messages" title="Link to this heading"></a></h2>
<details class="changelog">
<summary>Changelog</summary><div class="versionadded">
<p><span class="versionmodified added">Added in version 0.9.</span></p>
</div>
</details><p>Optionally you can pass a list of categories which filters the results of
<a class="reference internal" href="../api.html#flask.get_flashed_messages" title="flask.get_flashed_messages"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_flashed_messages()</span></code></a>. This is useful if you wish to
render each category in a separate block.</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">with</span> <span class="nv">errors</span> <span class="o">=</span> <span class="nv">get_flashed_messages</span><span class="o">(</span><span class="nv">category_filter</span><span class="o">=[</span><span class="s2">&quot;error&quot;</span><span class="o">])</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">errors</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;alert-message block-message error&quot;</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">a</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;close&quot;</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;#&quot;</span><span class="p">&gt;</span>×<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span>
<span class="cp">{%</span>- <span class="k">for</span> <span class="nv">msg</span> <span class="k">in</span> <span class="nv">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">msg</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="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">endwith</span> <span class="cp">%}</span>
</pre></div>
</div>
</section>
</section>
@ -94,20 +193,30 @@ user in a cookie in a <a class="reference internal" href="../api.html#flask.Flas
<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="#">Message Flashing</a><ul>
<li><a class="reference internal" href="#simple-flashing">Simple Flashing</a></li>
<li><a class="reference internal" href="#flashing-with-categories">Flashing With Categories</a></li>
<li><a class="reference internal" href="#filtering-flash-messages">Filtering Flash Messages</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="streaming.html" title="previous chapter">Streaming Contents</a>
<li>Next: <a href="methodoverrides.html" title="next chapter">Adding HTTP Method Overrides</a></ul>
<li>Previous: <a href="templateinheritance.html" title="previous chapter">Template Inheritance</a>
<li>Next: <a href="javascript.html" title="next chapter">JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON</a></ul>
</li>
</ul>
</li>
@ -131,4 +240,4 @@ user in a cookie in a <a class="reference internal" href="../api.html#flask.Flas
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Adding a favicon &#8212; Flask Documentation (3.2.x)</title>
<title>Patterns for Flask &#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="Streaming Contents" href="streaming.html" />
<link rel="prev" title="MongoDB with MongoEngine" href="mongoengine.html" />
<link rel="next" title="Large Applications as Packages" href="packages.html" />
<link rel="prev" title="Working with the Shell" href="../shell.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,73 +28,153 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="streaming.html" title="Streaming Contents"
<a href="packages.html" title="Large Applications as Packages"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="mongoengine.html" title="MongoDB with MongoEngine"
<a href="../shell.html" title="Working with the Shell"
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="">Adding a favicon</a></li>
<li class="nav-item nav-item-this"><a href="">Patterns for Flask</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="adding-a-favicon">
<h1>Adding a favicon<a class="headerlink" href="#adding-a-favicon" title="Link to this heading"></a></h1>
<p>A “favicon” is an icon used by browsers for tabs and bookmarks. This helps
to distinguish your website and to give it a unique brand.</p>
<p>A common question is how to add a favicon to a Flask application. First, of
course, you need an icon. It should be 16 × 16 pixels and in the ICO file
format. This is not a requirement but a de-facto standard supported by all
relevant browsers. Put the icon in your static directory as
<code class="file docutils literal notranslate"><span class="pre">favicon.ico</span></code>.</p>
<p>Now, to get browsers to find your icon, the correct way is to add a link
tag in your HTML. So, for example:</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&quot;shortcut icon&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;favicon.ico&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>Thats all you need for most browsers, however some really old ones do not
support this standard. The old de-facto standard is to serve this file,
with this name, at the website root. If your application is not mounted at
the root path of the domain you either need to configure the web server to
serve the icon at the root or if you cant do that youre out of luck. If
however your application is the root you can simply route a redirect:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span>
<span class="s2">&quot;/favicon.ico&quot;</span><span class="p">,</span>
<span class="n">endpoint</span><span class="o">=</span><span class="s2">&quot;favicon&quot;</span><span class="p">,</span>
<span class="n">redirect_to</span><span class="o">=</span><span class="n">url_for</span><span class="p">(</span><span class="s2">&quot;static&quot;</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="s2">&quot;favicon.ico&quot;</span><span class="p">),</span>
<span class="p">)</span>
</pre></div>
</div>
<p>If you want to save the extra redirect request you can also write a view
using <a class="reference internal" href="../api.html#flask.send_from_directory" title="flask.send_from_directory"><code class="xref py py-func docutils literal notranslate"><span class="pre">send_from_directory()</span></code></a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">os</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">send_from_directory</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/favicon.ico&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">favicon</span><span class="p">():</span>
<span class="k">return</span> <span class="n">send_from_directory</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">root_path</span><span class="p">,</span> <span class="s1">&#39;static&#39;</span><span class="p">),</span>
<span class="s1">&#39;favicon.ico&#39;</span><span class="p">,</span> <span class="n">mimetype</span><span class="o">=</span><span class="s1">&#39;image/vnd.microsoft.icon&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>We can leave out the explicit mimetype and it will be guessed, but we may
as well specify it to avoid the extra guessing, as it will always be the
same.</p>
<p>The above will serve the icon via your application and if possible its
better to configure your dedicated web server to serve it; refer to the
web servers documentation.</p>
<section id="see-also">
<h2>See also<a class="headerlink" href="#see-also" title="Link to this heading"></a></h2>
<ul class="simple">
<li><p>The <a class="reference external" href="https://en.wikipedia.org/wiki/Favicon">Favicon</a> article on
Wikipedia</p></li>
<section id="patterns-for-flask">
<h1>Patterns for Flask<a class="headerlink" href="#patterns-for-flask" title="Link to this heading"></a></h1>
<p>Certain features and interactions are common enough that you will find
them in most web applications. For example, many applications use a
relational database and user authentication. They will open a database
connection at the beginning of the request and get the information for
the logged in user. At the end of the request, the database connection
is closed.</p>
<p>These types of patterns may be a bit outside the scope of Flask itself,
but Flask makes it easy to implement them. Some common patterns are
collected in the following pages.</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="packages.html">Large Applications as Packages</a><ul>
<li class="toctree-l2"><a class="reference internal" href="packages.html#simple-packages">Simple Packages</a></li>
<li class="toctree-l2"><a class="reference internal" href="packages.html#working-with-blueprints">Working with Blueprints</a></li>
</ul>
</section>
</li>
<li class="toctree-l1"><a class="reference internal" href="appfactories.html">Application Factories</a><ul>
<li class="toctree-l2"><a class="reference internal" href="appfactories.html#basic-factories">Basic Factories</a></li>
<li class="toctree-l2"><a class="reference internal" href="appfactories.html#factories-extensions">Factories &amp; Extensions</a></li>
<li class="toctree-l2"><a class="reference internal" href="appfactories.html#using-applications">Using Applications</a></li>
<li class="toctree-l2"><a class="reference internal" href="appfactories.html#factory-improvements">Factory Improvements</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="appdispatch.html">Application Dispatching</a><ul>
<li class="toctree-l2"><a class="reference internal" href="appdispatch.html#working-with-this-document">Working with this Document</a></li>
<li class="toctree-l2"><a class="reference internal" href="appdispatch.html#combining-applications">Combining Applications</a></li>
<li class="toctree-l2"><a class="reference internal" href="appdispatch.html#dispatch-by-subdomain">Dispatch by Subdomain</a></li>
<li class="toctree-l2"><a class="reference internal" href="appdispatch.html#dispatch-by-path">Dispatch by Path</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="urlprocessors.html">Using URL Processors</a><ul>
<li class="toctree-l2"><a class="reference internal" href="urlprocessors.html#internationalized-application-urls">Internationalized Application URLs</a></li>
<li class="toctree-l2"><a class="reference internal" href="urlprocessors.html#internationalized-blueprint-urls">Internationalized Blueprint URLs</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="sqlite3.html">Using SQLite 3 with Flask</a><ul>
<li class="toctree-l2"><a class="reference internal" href="sqlite3.html#connect-on-demand">Connect on Demand</a></li>
<li class="toctree-l2"><a class="reference internal" href="sqlite3.html#easy-querying">Easy Querying</a></li>
<li class="toctree-l2"><a class="reference internal" href="sqlite3.html#initial-schemas">Initial Schemas</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="sqlalchemy.html">SQLAlchemy in Flask</a><ul>
<li class="toctree-l2"><a class="reference internal" href="sqlalchemy.html#flask-sqlalchemy-extension">Flask-SQLAlchemy Extension</a></li>
<li class="toctree-l2"><a class="reference internal" href="sqlalchemy.html#declarative">Declarative</a></li>
<li class="toctree-l2"><a class="reference internal" href="sqlalchemy.html#manual-object-relational-mapping">Manual Object Relational Mapping</a></li>
<li class="toctree-l2"><a class="reference internal" href="sqlalchemy.html#sql-abstraction-layer">SQL Abstraction Layer</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="fileuploads.html">Uploading Files</a><ul>
<li class="toctree-l2"><a class="reference internal" href="fileuploads.html#a-gentle-introduction">A Gentle Introduction</a></li>
<li class="toctree-l2"><a class="reference internal" href="fileuploads.html#improving-uploads">Improving Uploads</a></li>
<li class="toctree-l2"><a class="reference internal" href="fileuploads.html#upload-progress-bars">Upload Progress Bars</a></li>
<li class="toctree-l2"><a class="reference internal" href="fileuploads.html#an-easier-solution">An Easier Solution</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="caching.html">Caching</a></li>
<li class="toctree-l1"><a class="reference internal" href="viewdecorators.html">View Decorators</a><ul>
<li class="toctree-l2"><a class="reference internal" href="viewdecorators.html#login-required-decorator">Login Required Decorator</a></li>
<li class="toctree-l2"><a class="reference internal" href="viewdecorators.html#caching-decorator">Caching Decorator</a></li>
<li class="toctree-l2"><a class="reference internal" href="viewdecorators.html#templating-decorator">Templating Decorator</a></li>
<li class="toctree-l2"><a class="reference internal" href="viewdecorators.html#endpoint-decorator">Endpoint Decorator</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="wtforms.html">Form Validation with WTForms</a><ul>
<li class="toctree-l2"><a class="reference internal" href="wtforms.html#the-forms">The Forms</a></li>
<li class="toctree-l2"><a class="reference internal" href="wtforms.html#in-the-view">In the View</a></li>
<li class="toctree-l2"><a class="reference internal" href="wtforms.html#forms-in-templates">Forms in Templates</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="templateinheritance.html">Template Inheritance</a><ul>
<li class="toctree-l2"><a class="reference internal" href="templateinheritance.html#base-template">Base Template</a></li>
<li class="toctree-l2"><a class="reference internal" href="templateinheritance.html#child-template">Child Template</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="flashing.html">Message Flashing</a><ul>
<li class="toctree-l2"><a class="reference internal" href="flashing.html#simple-flashing">Simple Flashing</a></li>
<li class="toctree-l2"><a class="reference internal" href="flashing.html#flashing-with-categories">Flashing With Categories</a></li>
<li class="toctree-l2"><a class="reference internal" href="flashing.html#filtering-flash-messages">Filtering Flash Messages</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="javascript.html">JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON</a><ul>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#rendering-templates">Rendering Templates</a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#generating-urls">Generating URLs</a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#making-a-request-with-fetch">Making a Request with <code class="docutils literal notranslate"><span class="pre">fetch</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#following-redirects">Following Redirects</a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#replacing-content">Replacing Content</a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#return-json-from-views">Return JSON from Views</a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#receiving-json-in-views">Receiving JSON in Views</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="lazyloading.html">Lazily Loading Views</a><ul>
<li class="toctree-l2"><a class="reference internal" href="lazyloading.html#converting-to-centralized-url-map">Converting to Centralized URL Map</a></li>
<li class="toctree-l2"><a class="reference internal" href="lazyloading.html#loading-late">Loading Late</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="mongoengine.html">MongoDB with MongoEngine</a><ul>
<li class="toctree-l2"><a class="reference internal" href="mongoengine.html#configuration">Configuration</a></li>
<li class="toctree-l2"><a class="reference internal" href="mongoengine.html#mapping-documents">Mapping Documents</a></li>
<li class="toctree-l2"><a class="reference internal" href="mongoengine.html#creating-data">Creating Data</a></li>
<li class="toctree-l2"><a class="reference internal" href="mongoengine.html#queries">Queries</a></li>
<li class="toctree-l2"><a class="reference internal" href="mongoengine.html#documentation">Documentation</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="favicon.html">Adding a favicon</a><ul>
<li class="toctree-l2"><a class="reference internal" href="favicon.html#see-also">See also</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="streaming.html">Streaming Contents</a><ul>
<li class="toctree-l2"><a class="reference internal" href="streaming.html#basic-usage">Basic Usage</a></li>
<li class="toctree-l2"><a class="reference internal" href="streaming.html#streaming-from-templates">Streaming from Templates</a></li>
<li class="toctree-l2"><a class="reference internal" href="streaming.html#streaming-with-context">Streaming with Context</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="deferredcallbacks.html">Deferred Request Callbacks</a></li>
<li class="toctree-l1"><a class="reference internal" href="methodoverrides.html">Adding HTTP Method Overrides</a></li>
<li class="toctree-l1"><a class="reference internal" href="requestchecksum.html">Request Content Checksums</a></li>
<li class="toctree-l1"><a class="reference internal" href="celery.html">Background Tasks with Celery</a><ul>
<li class="toctree-l2"><a class="reference internal" href="celery.html#install">Install</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#integrate-celery-with-flask">Integrate Celery with Flask</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#application-factory">Application Factory</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#defining-tasks">Defining Tasks</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#calling-tasks">Calling Tasks</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#getting-results">Getting Results</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#passing-data-to-tasks">Passing Data to Tasks</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="subclassing.html">Subclassing Flask</a></li>
<li class="toctree-l1"><a class="reference internal" href="singlepageapplications.html">Single-Page Applications</a></li>
</ul>
</div>
</section>
@ -105,29 +185,18 @@ Wikipedia</p></li>
<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="#">Adding a favicon</a><ul>
<li><a class="reference internal" href="#see-also">See also</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="mongoengine.html" title="previous chapter">MongoDB with MongoEngine</a>
<li>Next: <a href="streaming.html" title="next chapter">Streaming Contents</a></ul>
</li>
<li>Previous: <a href="../shell.html" title="previous chapter">Working with the Shell</a>
<li>Next: <a href="packages.html" title="next chapter">Large Applications as Packages</a>
</ul>
</li>
</ul>
@ -150,4 +219,4 @@ Wikipedia</p></li>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Uploading Files &#8212; Flask Documentation (3.2.x)</title>
<title>JavaScript, fetch, and JSON &#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="Caching" href="caching.html" />
<link rel="prev" title="SQLAlchemy in Flask" href="sqlalchemy.html" />
<link rel="next" title="Lazily Loading Views" href="lazyloading.html" />
<link rel="prev" title="Message Flashing" href="flashing.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,189 +28,227 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="caching.html" title="Caching"
<a href="lazyloading.html" title="Lazily Loading Views"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="sqlalchemy.html" title="SQLAlchemy in Flask"
<a href="flashing.html" title="Message Flashing"
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="">Uploading Files</a></li>
<li class="nav-item nav-item-this"><a href="">JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="uploading-files">
<h1>Uploading Files<a class="headerlink" href="#uploading-files" title="Link to this heading"></a></h1>
<p>Ah yes, the good old problem of file uploads. The basic idea of file
uploads is actually quite simple. It basically works like this:</p>
<ol class="arabic simple">
<li><p>A <code class="docutils literal notranslate"><span class="pre">&lt;form&gt;</span></code> tag is marked with <code class="docutils literal notranslate"><span class="pre">enctype=multipart/form-data</span></code>
and an <code class="docutils literal notranslate"><span class="pre">&lt;input</span> <span class="pre">type=file&gt;</span></code> is placed in that form.</p></li>
<li><p>The application accesses the file from the <code class="xref py py-attr docutils literal notranslate"><span class="pre">files</span></code>
dictionary on the request object.</p></li>
<li><p>use the <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/datastructures/#werkzeug.datastructures.FileStorage.save" title="(in Werkzeug v3.1.x)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">save()</span></code></a> method of the file to save
the file permanently somewhere on the filesystem.</p></li>
</ol>
<section id="a-gentle-introduction">
<h2>A Gentle Introduction<a class="headerlink" href="#a-gentle-introduction" title="Link to this heading"></a></h2>
<p>Lets start with a very basic application that uploads a file to a
specific upload folder and displays a file to the user. Lets look at the
bootstrapping code for our application:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">os</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">flash</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">redirect</span><span class="p">,</span> <span class="n">url_for</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">werkzeug.utils</span><span class="w"> </span><span class="kn">import</span> <span class="n">secure_filename</span>
<span class="n">UPLOAD_FOLDER</span> <span class="o">=</span> <span class="s1">&#39;/path/to/the/uploads&#39;</span>
<span class="n">ALLOWED_EXTENSIONS</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;txt&#39;</span><span class="p">,</span> <span class="s1">&#39;pdf&#39;</span><span class="p">,</span> <span class="s1">&#39;png&#39;</span><span class="p">,</span> <span class="s1">&#39;jpg&#39;</span><span class="p">,</span> <span class="s1">&#39;jpeg&#39;</span><span class="p">,</span> <span class="s1">&#39;gif&#39;</span><span class="p">}</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="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;UPLOAD_FOLDER&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">UPLOAD_FOLDER</span>
<section id="javascript-fetch-and-json">
<h1>JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON<a class="headerlink" href="#javascript-fetch-and-json" title="Link to this heading"></a></h1>
<p>You may want to make your HTML page dynamic, by changing data without
reloading the entire page. Instead of submitting an HTML <code class="docutils literal notranslate"><span class="pre">&lt;form&gt;</span></code> and
performing a redirect to re-render the template, you can add
<a class="reference external" href="https://developer.mozilla.org/Web/JavaScript">JavaScript</a> that calls <a class="reference external" href="https://developer.mozilla.org/Web/API/Fetch_API"><code class="docutils literal notranslate"><span class="pre">fetch()</span></code></a> and replaces content on the page.</p>
<p><a class="reference external" href="https://developer.mozilla.org/Web/API/Fetch_API"><code class="docutils literal notranslate"><span class="pre">fetch()</span></code></a> is the modern, built-in JavaScript solution to making
requests from a page. You may have heard of other “AJAX” methods and
libraries, such as <a class="reference external" href="https://developer.mozilla.org/Web/API/XMLHttpRequest"><code class="docutils literal notranslate"><span class="pre">XMLHttpRequest()</span></code></a> or <a class="reference external" href="https://jquery.com/">jQuery</a>. These are no longer needed in
modern browsers, although you may choose to use them or another library
depending on your applications requirements. These docs will only focus
on built-in JavaScript features.</p>
<section id="rendering-templates">
<h2>Rendering Templates<a class="headerlink" href="#rendering-templates" title="Link to this heading"></a></h2>
<p>It is important to understand the difference between templates and
JavaScript. Templates are rendered on the server, before the response is
sent to the users browser. JavaScript runs in the users browser, after
the template is rendered and sent. Therefore, it is impossible to use
JavaScript to affect how the Jinja template is rendered, but it is
possible to render data into the JavaScript that will run.</p>
<p>To provide data to JavaScript when rendering the template, use the
<a class="reference external" href="https://jinja.palletsprojects.com/en/stable/templates/#jinja-filters.tojson" title="(in Jinja v3.1.x)"><code class="xref py py-func docutils literal notranslate"><span class="pre">tojson()</span></code></a> filter in a <code class="docutils literal notranslate"><span class="pre">&lt;script&gt;</span></code> block. This will
convert the data to a valid JavaScript object, and ensure that any
unsafe HTML characters are rendered safely. If you do not use the
<code class="docutils literal notranslate"><span class="pre">tojson</span></code> filter, you will get a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code> in the browser
console.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">data</span> <span class="o">=</span> <span class="n">generate_report</span><span class="p">()</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">&quot;report.html&quot;</span><span class="p">,</span> <span class="n">chart_data</span><span class="o">=</span><span class="n">data</span><span class="p">)</span>
</pre></div>
</div>
<p>So first we need a couple of imports. Most should be straightforward, the
<code class="xref py py-func docutils literal notranslate"><span class="pre">werkzeug.secure_filename()</span></code> is explained a little bit later. The
<code class="docutils literal notranslate"><span class="pre">UPLOAD_FOLDER</span></code> is where we will store the uploaded files and the
<code class="docutils literal notranslate"><span class="pre">ALLOWED_EXTENSIONS</span></code> is the set of allowed file extensions.</p>
<p>Why do we limit the extensions that are allowed? You probably dont want
your users to be able to upload everything there if the server is directly
sending out the data to the client. That way you can make sure that users
are not able to upload HTML files that would cause XSS problems (see
<a class="reference internal" href="../web-security.html#security-xss"><span class="std std-ref">Cross-Site Scripting (XSS)</span></a>). Also make sure to disallow <code class="docutils literal notranslate"><span class="pre">.php</span></code> files if the server
executes them, but who has PHP installed on their server, right? :)</p>
<p>Next the functions that check if an extension is valid and that uploads
the file and redirects the user to the URL for the uploaded file:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">allowed_file</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
<span class="k">return</span> <span class="s1">&#39;.&#39;</span> <span class="ow">in</span> <span class="n">filename</span> <span class="ow">and</span> \
<span class="n">filename</span><span class="o">.</span><span class="n">rsplit</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="n">ALLOWED_EXTENSIONS</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="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">upload_file</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="p">:</span>
<span class="c1"># check if the post request has the file part</span>
<span class="k">if</span> <span class="s1">&#39;file&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">request</span><span class="o">.</span><span class="n">files</span><span class="p">:</span>
<span class="n">flash</span><span class="p">(</span><span class="s1">&#39;No file part&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">url</span><span class="p">)</span>
<span class="n">file</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">files</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">]</span>
<span class="c1"># If the user does not select a file, the browser submits an</span>
<span class="c1"># empty file without a filename.</span>
<span class="k">if</span> <span class="n">file</span><span class="o">.</span><span class="n">filename</span> <span class="o">==</span> <span class="s1">&#39;&#39;</span><span class="p">:</span>
<span class="n">flash</span><span class="p">(</span><span class="s1">&#39;No selected file&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">url</span><span class="p">)</span>
<span class="k">if</span> <span class="n">file</span> <span class="ow">and</span> <span class="n">allowed_file</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">filename</span><span class="p">):</span>
<span class="n">filename</span> <span class="o">=</span> <span class="n">secure_filename</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>
<span class="n">file</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;UPLOAD_FOLDER&#39;</span><span class="p">],</span> <span class="n">filename</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;download_file&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">filename</span><span class="p">))</span>
<span class="k">return</span> <span class="s1">&#39;&#39;&#39;</span>
<span class="s1"> &lt;!doctype html&gt;</span>
<span class="s1"> &lt;title&gt;Upload new File&lt;/title&gt;</span>
<span class="s1"> &lt;h1&gt;Upload new File&lt;/h1&gt;</span>
<span class="s1"> &lt;form method=post enctype=multipart/form-data&gt;</span>
<span class="s1"> &lt;input type=file name=file&gt;</span>
<span class="s1"> &lt;input type=submit value=Upload&gt;</span>
<span class="s1"> &lt;/form&gt;</span>
<span class="s1"> &#39;&#39;&#39;</span>
<div class="highlight-jinja notranslate"><div class="highlight"><pre><span></span><span class="x">&lt;script&gt;</span>
<span class="x"> const chart_data = </span><span class="cp">{{</span> <span class="nv">chart_data</span><span class="o">|</span><span class="nf">tojson</span> <span class="cp">}}</span>
<span class="x"> chartLib.makeChart(chart_data)</span>
<span class="x">&lt;/script&gt;</span>
</pre></div>
</div>
<p>So what does that <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/utils/#werkzeug.utils.secure_filename" title="(in Werkzeug v3.1.x)"><code class="xref py py-func docutils literal notranslate"><span class="pre">secure_filename()</span></code></a> function actually do?
Now the problem is that there is that principle called “never trust user
input”. This is also true for the filename of an uploaded file. All
submitted form data can be forged, and filenames can be dangerous. For
the moment just remember: always use that function to secure a filename
before storing it directly on the filesystem.</p>
<div class="admonition-information-for-the-pros admonition">
<p class="admonition-title">Information for the Pros</p>
<p>So youre interested in what that <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/utils/#werkzeug.utils.secure_filename" title="(in Werkzeug v3.1.x)"><code class="xref py py-func docutils literal notranslate"><span class="pre">secure_filename()</span></code></a>
function does and what the problem is if youre not using it? So just
imagine someone would send the following information as <code class="code docutils literal notranslate"><span class="pre">filename</span></code> to
your application:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">filename</span> <span class="o">=</span> <span class="s2">&quot;../../../../home/username/.bashrc&quot;</span>
<p>A less common pattern is to add the data to a <code class="docutils literal notranslate"><span class="pre">data-</span></code> attribute on an
HTML tag. In this case, you must use single quotes around the value, not
double quotes, otherwise you will produce invalid or unsafe HTML.</p>
<div class="highlight-jinja notranslate"><div class="highlight"><pre><span></span><span class="x">&lt;div data-chart=&#39;</span><span class="cp">{{</span> <span class="nv">chart_data</span><span class="o">|</span><span class="nf">tojson</span> <span class="cp">}}</span><span class="x">&#39;&gt;&lt;/div&gt;</span>
</pre></div>
</div>
<p>Assuming the number of <code class="docutils literal notranslate"><span class="pre">../</span></code> is correct and you would join this with
the <code class="docutils literal notranslate"><span class="pre">UPLOAD_FOLDER</span></code> the user might have the ability to modify a file on
the servers filesystem he or she should not modify. This does require some
knowledge about how the application looks like, but trust me, hackers
are patient :)</p>
<p>Now lets look how that function works:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">secure_filename</span><span class="p">(</span><span class="s1">&#39;../../../../home/username/.bashrc&#39;</span><span class="p">)</span>
<span class="go">&#39;home_username_.bashrc&#39;</span>
</section>
<section id="generating-urls">
<h2>Generating URLs<a class="headerlink" href="#generating-urls" title="Link to this heading"></a></h2>
<p>The other way to get data from the server to JavaScript is to make a
request for it. First, you need to know the URL to request.</p>
<p>The simplest way to generate URLs is to continue to use
<a class="reference internal" href="../api.html#flask.url_for" title="flask.url_for"><code class="xref py py-func docutils literal notranslate"><span class="pre">url_for()</span></code></a> when rendering the template. For example:</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">const</span><span class="w"> </span><span class="nx">user_url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">url_for</span><span class="p">(</span><span class="s2">&quot;user&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">id</span><span class="o">=</span><span class="nx">current_user</span><span class="p">.</span><span class="nx">id</span><span class="p">)</span><span class="o">|</span><span class="nx">tojson</span><span class="w"> </span><span class="p">}}</span>
<span class="nx">fetch</span><span class="p">(</span><span class="nx">user_url</span><span class="p">).</span><span class="nx">then</span><span class="p">(...)</span>
</pre></div>
</div>
</div>
<p>We want to be able to serve the uploaded files so they can be downloaded
by users. Well define a <code class="docutils literal notranslate"><span class="pre">download_file</span></code> view to serve files in the
upload folder by name. <code class="docutils literal notranslate"><span class="pre">url_for(&quot;download_file&quot;,</span> <span class="pre">name=name)</span></code> generates
download URLs.</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">send_from_directory</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/uploads/&lt;name&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">download_file</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
<span class="k">return</span> <span class="n">send_from_directory</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s2">&quot;UPLOAD_FOLDER&quot;</span><span class="p">],</span> <span class="n">name</span><span class="p">)</span>
<p>However, you might need to generate a URL based on information you only
know in JavaScript. As discussed above, JavaScript runs in the users
browser, not as part of the template rendering, so you cant use
<code class="docutils literal notranslate"><span class="pre">url_for</span></code> at that point.</p>
<p>In this case, you need to know the “root URL” under which your
application is served. In simple setups, this is <code class="docutils literal notranslate"><span class="pre">/</span></code>, but it might
also be something else, like <code class="docutils literal notranslate"><span class="pre">https://example.com/myapp/</span></code>.</p>
<p>A simple way to tell your JavaScript code about this root is to set it
as a global variable when rendering the template. Then you can use it
when generating URLs from JavaScript.</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">const</span><span class="w"> </span><span class="nx">SCRIPT_ROOT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">request</span><span class="p">.</span><span class="nx">script_root</span><span class="o">|</span><span class="nx">tojson</span><span class="w"> </span><span class="p">}}</span>
<span class="kd">let</span><span class="w"> </span><span class="nx">user_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="c1">// do something to get a user id from the page</span>
<span class="kd">let</span><span class="w"> </span><span class="nx">user_url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sb">`</span><span class="si">${</span><span class="nx">SCRIPT_ROOT</span><span class="si">}</span><span class="sb">/user/</span><span class="si">${</span><span class="nx">user_id</span><span class="si">}</span><span class="sb">`</span>
<span class="nx">fetch</span><span class="p">(</span><span class="nx">user_url</span><span class="p">).</span><span class="nx">then</span><span class="p">(...)</span>
</pre></div>
</div>
<p>If youre using middleware or the HTTP server to serve files, you can
register the <code class="docutils literal notranslate"><span class="pre">download_file</span></code> endpoint as <code class="docutils literal notranslate"><span class="pre">build_only</span></code> so <code class="docutils literal notranslate"><span class="pre">url_for</span></code>
will work without a view function.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span>
<span class="s2">&quot;/uploads/&lt;name&gt;&quot;</span><span class="p">,</span> <span class="n">endpoint</span><span class="o">=</span><span class="s2">&quot;download_file&quot;</span><span class="p">,</span> <span class="n">build_only</span><span class="o">=</span><span class="kc">True</span>
</section>
<section id="making-a-request-with-fetch">
<h2>Making a Request with <code class="docutils literal notranslate"><span class="pre">fetch</span></code><a class="headerlink" href="#making-a-request-with-fetch" title="Link to this heading"></a></h2>
<p><a class="reference external" href="https://developer.mozilla.org/Web/API/Fetch_API"><code class="docutils literal notranslate"><span class="pre">fetch()</span></code></a> takes two arguments, a URL and an object with other options,
and returns a <a class="reference external" href="https://developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/Promise"><code class="docutils literal notranslate"><span class="pre">Promise</span></code></a>. We wont cover all the available options, and
will only use <code class="docutils literal notranslate"><span class="pre">then()</span></code> on the promise, not other callbacks or
<code class="docutils literal notranslate"><span class="pre">await</span></code> syntax. Read the linked MDN docs for more information about
those features.</p>
<p>By default, the GET method is used. If the response contains JSON, it
can be used with a <code class="docutils literal notranslate"><span class="pre">then()</span></code> callback chain.</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">const</span><span class="w"> </span><span class="nx">room_url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">url_for</span><span class="p">(</span><span class="s2">&quot;room_detail&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">id</span><span class="o">=</span><span class="nx">room</span><span class="p">.</span><span class="nx">id</span><span class="p">)</span><span class="o">|</span><span class="nx">tojson</span><span class="w"> </span><span class="p">}}</span>
<span class="nx">fetch</span><span class="p">(</span><span class="nx">room_url</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">response</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">())</span>
<span class="w"> </span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">data</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// data is a parsed JSON object</span>
<span class="w"> </span><span class="p">})</span>
</pre></div>
</div>
<p>To send data, use a data method such as POST, and pass the <code class="docutils literal notranslate"><span class="pre">body</span></code>
option. The most common types for data are form data or JSON data.</p>
<p>To send form data, pass a populated <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/API/FormData"><code class="docutils literal notranslate"><span class="pre">FormData</span></code></a> object. This uses the
same format as an HTML form, and would be accessed with <code class="docutils literal notranslate"><span class="pre">request.form</span></code>
in a Flask view.</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">let</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">FormData</span><span class="p">()</span>
<span class="nx">data</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="s2">&quot;name&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;Flask Room&quot;</span><span class="p">)</span>
<span class="nx">data</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="s2">&quot;description&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;Talk about Flask here.&quot;</span><span class="p">)</span>
<span class="nx">fetch</span><span class="p">(</span><span class="nx">room_url</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;method&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;POST&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;body&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">data</span><span class="p">,</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(...)</span>
</pre></div>
</div>
<p>In general, prefer sending request data as form data, as would be used
when submitting an HTML form. JSON can represent more complex data, but
unless you need that its better to stick with the simpler format. When
sending JSON data, the <code class="docutils literal notranslate"><span class="pre">Content-Type:</span> <span class="pre">application/json</span></code> header must be
sent as well, otherwise Flask will return a 400 error.</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">let</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;name&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Flask Room&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;description&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Talk about Flask here.&quot;</span><span class="p">,</span>
<span class="p">}</span>
<span class="nx">fetch</span><span class="p">(</span><span class="nx">room_url</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;method&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;POST&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;headers&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="s2">&quot;Content-Type&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;application/json&quot;</span><span class="p">},</span>
<span class="w"> </span><span class="s2">&quot;body&quot;</span><span class="o">:</span><span class="w"> </span><span class="nb">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">data</span><span class="p">),</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(...)</span>
</pre></div>
</div>
</section>
<section id="following-redirects">
<h2>Following Redirects<a class="headerlink" href="#following-redirects" title="Link to this heading"></a></h2>
<p>A response might be a redirect, for example if you logged in with
JavaScript instead of a traditional HTML form, and your view returned
a redirect instead of JSON. JavaScript requests do follow redirects, but
they dont change the page. If you want to make the page change you can
inspect the response and apply the redirect manually.</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="nx">fetch</span><span class="p">(</span><span class="s2">&quot;/login&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="s2">&quot;body&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">...}).</span><span class="nx">then</span><span class="p">(</span>
<span class="w"> </span><span class="nx">response</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">redirected</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">response</span><span class="p">.</span><span class="nx">url</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">showLoginError</span><span class="p">()</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">)</span>
</pre></div>
</div>
</section>
<section id="improving-uploads">
<h2>Improving Uploads<a class="headerlink" href="#improving-uploads" title="Link to this heading"></a></h2>
<details class="changelog">
<summary>Changelog</summary><div class="versionadded">
<p><span class="versionmodified added">Added in version 0.6.</span></p>
</div>
</details><p>So how exactly does Flask handle uploads? Well it will store them in the
webservers memory if the files are reasonably small, otherwise in a
temporary location (as returned by <a class="reference external" href="https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir" title="(in Python v3.13)"><code class="xref py py-func docutils literal notranslate"><span class="pre">tempfile.gettempdir()</span></code></a>). But how
do you specify the maximum file size after which an upload is aborted? By
default Flask will happily accept file uploads with an unlimited amount of
memory, but you can limit that by setting the <code class="docutils literal notranslate"><span class="pre">MAX_CONTENT_LENGTH</span></code>
config key:</p>
<div class="highlight-default 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="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;MAX_CONTENT_LENGTH&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">16</span> <span class="o">*</span> <span class="mi">1000</span> <span class="o">*</span> <span class="mi">1000</span>
<section id="replacing-content">
<h2>Replacing Content<a class="headerlink" href="#replacing-content" title="Link to this heading"></a></h2>
<p>A response might be new HTML, either a new section of the page to add or
replace, or an entirely new page. In general, if youre returning the
entire page, it would be better to handle that with a redirect as shown
in the previous section. The following example shows how to replace a
<code class="docutils literal notranslate"><span class="pre">&lt;div&gt;</span></code> with the HTML returned by a request.</p>
<div class="highlight-html notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;geology-fact&quot;</span><span class="p">&gt;</span>
{{ include &quot;geology_fact.html&quot; }}
<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">geology_url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">url_for</span><span class="p">(</span><span class="s2">&quot;geology_fact&quot;</span><span class="p">)</span><span class="o">|</span><span class="nx">tojson</span><span class="w"> </span><span class="p">}}</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">geology_div</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">&quot;geology-fact&quot;</span><span class="p">)</span>
<span class="w"> </span><span class="nx">fetch</span><span class="p">(</span><span class="nx">geology_url</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">response</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">response</span><span class="p">.</span><span class="nx">text</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">text</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">geology_div</span><span class="p">.</span><span class="nx">innerHTML</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">text</span><span class="p">)</span>
<span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</pre></div>
</div>
<p>The code above will limit the maximum allowed payload to 16 megabytes.
If a larger file is transmitted, Flask will raise a
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.RequestEntityTooLarge" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RequestEntityTooLarge</span></code></a> exception.</p>
<div class="admonition-connection-reset-issue admonition">
<p class="admonition-title">Connection Reset Issue</p>
<p>When using the local development server, you may get a connection
reset error instead of a 413 response. You will get the correct
status response when running the app with a production WSGI server.</p>
</section>
<section id="return-json-from-views">
<h2>Return JSON from Views<a class="headerlink" href="#return-json-from-views" title="Link to this heading"></a></h2>
<p>To return a JSON object from your API view, you can directly return a
dict from the view. It will be serialized to JSON automatically.</p>
<div class="highlight-python 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="s2">&quot;/user/&lt;int:id&gt;&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user_detail</span><span class="p">(</span><span class="nb">id</span><span class="p">):</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">get_or_404</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span>
<span class="k">return</span> <span class="p">{</span>
<span class="s2">&quot;username&quot;</span><span class="p">:</span> <span class="n">User</span><span class="o">.</span><span class="n">username</span><span class="p">,</span>
<span class="s2">&quot;email&quot;</span><span class="p">:</span> <span class="n">User</span><span class="o">.</span><span class="n">email</span><span class="p">,</span>
<span class="s2">&quot;picture&quot;</span><span class="p">:</span> <span class="n">url_for</span><span class="p">(</span><span class="s2">&quot;static&quot;</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="sa">f</span><span class="s2">&quot;users/</span><span class="si">{</span><span class="nb">id</span><span class="si">}</span><span class="s2">/profile.png&quot;</span><span class="p">),</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This feature was added in Flask 0.6 but can be achieved in older versions
as well by subclassing the request object. For more information on that
consult the Werkzeug documentation on file handling.</p>
<p>If you want to return another JSON type, use the
<a class="reference internal" href="../api.html#flask.json.jsonify" title="flask.json.jsonify"><code class="xref py py-func docutils literal notranslate"><span class="pre">jsonify()</span></code></a> function, which creates a response object
with the given data serialized to JSON.</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">jsonify</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/users&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user_list</span><span class="p">():</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">([</span><span class="n">u</span><span class="o">.</span><span class="n">to_json</span><span class="p">()</span> <span class="k">for</span> <span class="n">u</span> <span class="ow">in</span> <span class="n">users</span><span class="p">])</span>
</pre></div>
</div>
<p>It is usually not a good idea to return file data in a JSON response.
JSON cannot represent binary data directly, so it must be base64
encoded, which can be slow, takes more bandwidth to send, and is not as
easy to cache. Instead, serve files using one view, and generate a URL
to the desired file to include in the JSON. Then the client can make a
separate request to get the linked resource after getting the JSON.</p>
</section>
<section id="upload-progress-bars">
<h2>Upload Progress Bars<a class="headerlink" href="#upload-progress-bars" title="Link to this heading"></a></h2>
<p>A while ago many developers had the idea to read the incoming file in
small chunks and store the upload progress in the database to be able to
poll the progress with JavaScript from the client. The client asks the
server every 5 seconds how much it has transmitted, but this is
something it should already know.</p>
</section>
<section id="an-easier-solution">
<h2>An Easier Solution<a class="headerlink" href="#an-easier-solution" title="Link to this heading"></a></h2>
<p>Now there are better solutions that work faster and are more reliable. There
are JavaScript libraries like <a class="reference external" href="https://jquery.com/">jQuery</a> that have form plugins to ease the
construction of progress bar.</p>
<p>Because the common pattern for file uploads exists almost unchanged in all
applications dealing with uploads, there are also some Flask extensions that
implement a full fledged upload mechanism that allows controlling which
file extensions are allowed to be uploaded.</p>
<section id="receiving-json-in-views">
<h2>Receiving JSON in Views<a class="headerlink" href="#receiving-json-in-views" title="Link to this heading"></a></h2>
<p>Use the <a class="reference internal" href="../api.html#flask.Request.json" title="flask.Request.json"><code class="xref py py-attr docutils literal notranslate"><span class="pre">json</span></code></a> property of 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> object to decode the requests body as JSON. If
the body is not valid JSON, or the <code class="docutils literal notranslate"><span class="pre">Content-Type</span></code> header is not set to
<code class="docutils literal notranslate"><span class="pre">application/json</span></code>, a 400 Bad Request error will be raised.</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">request</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">&quot;/user/&lt;int:id&gt;&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user_update</span><span class="p">(</span><span class="nb">id</span><span class="p">):</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">get_or_404</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span>
<span class="n">user</span><span class="o">.</span><span class="n">update_from_json</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">json</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
<span class="k">return</span> <span class="n">user</span><span class="o">.</span><span class="n">to_json</span><span class="p">()</span>
</pre></div>
</div>
</section>
</section>
@ -222,20 +260,23 @@ file extensions are allowed to be uploaded.</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"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Uploading Files</a><ul>
<li><a class="reference internal" href="#a-gentle-introduction">A Gentle Introduction</a></li>
<li><a class="reference internal" href="#improving-uploads">Improving Uploads</a></li>
<li><a class="reference internal" href="#upload-progress-bars">Upload Progress Bars</a></li>
<li><a class="reference internal" href="#an-easier-solution">An Easier Solution</a></li>
<li><a class="reference internal" href="#">JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON</a><ul>
<li><a class="reference internal" href="#rendering-templates">Rendering Templates</a></li>
<li><a class="reference internal" href="#generating-urls">Generating URLs</a></li>
<li><a class="reference internal" href="#making-a-request-with-fetch">Making a Request with <code class="docutils literal notranslate"><span class="pre">fetch</span></code></a></li>
<li><a class="reference internal" href="#following-redirects">Following Redirects</a></li>
<li><a class="reference internal" href="#replacing-content">Replacing Content</a></li>
<li><a class="reference internal" href="#return-json-from-views">Return JSON from Views</a></li>
<li><a class="reference internal" href="#receiving-json-in-views">Receiving JSON in Views</a></li>
</ul>
</li>
</ul>
@ -245,8 +286,8 @@ file extensions are allowed to be uploaded.</p>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="sqlalchemy.html" title="previous chapter">SQLAlchemy in Flask</a>
<li>Next: <a href="caching.html" title="next chapter">Caching</a></ul>
<li>Previous: <a href="flashing.html" title="previous chapter">Message Flashing</a>
<li>Next: <a href="lazyloading.html" title="next chapter">Lazily Loading Views</a></ul>
</li>
</ul>
</li>
@ -270,4 +311,4 @@ file extensions are allowed to be uploaded.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Message Flashing &#8212; Flask Documentation (3.2.x)</title>
<title>AJAX with jQuery &#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,6 @@
<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="JavaScript, fetch, and JSON" href="javascript.html" />
<link rel="prev" title="Template Inheritance" href="templateinheritance.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -27,162 +25,19 @@
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="javascript.html" title="JavaScript, fetch, and JSON"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="templateinheritance.html" title="Template Inheritance"
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="">Message Flashing</a></li>
<li class="nav-item nav-item-this"><a href="">AJAX with jQuery</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="message-flashing">
<h1>Message Flashing<a class="headerlink" href="#message-flashing" title="Link to this heading"></a></h1>
<p>Good applications and user interfaces are all about feedback. If the user
does not get enough feedback they will probably end up hating the
application. Flask provides a really simple way to give feedback to a
user with the flashing system. The flashing system basically makes it
possible to record a message at the end of a request and access it next
request and only next request. This is usually combined with a layout
template that does this. Note that browsers and sometimes web servers enforce
a limit on cookie sizes. This means that flashing messages that are too
large for session cookies causes message flashing to fail silently.</p>
<section id="simple-flashing">
<h2>Simple Flashing<a class="headerlink" href="#simple-flashing" title="Link to this heading"></a></h2>
<p>So here is a full example:</p>
<div class="highlight-default 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">flash</span><span class="p">,</span> <span class="n">redirect</span><span class="p">,</span> <span class="n">render_template</span><span class="p">,</span> \
<span class="n">request</span><span class="p">,</span> <span class="n">url_for</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="n">app</span><span class="o">.</span><span class="n">secret_key</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">&#39;_5#y2L&quot;F4Q8z</span><span class="se">\n\xec</span><span class="s1">]/&#39;</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">index</span><span class="p">():</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">&#39;index.html&#39;</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;/login&#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">login</span><span class="p">():</span>
<span class="n">error</span> <span class="o">=</span> <span class="kc">None</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="p">:</span>
<span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="p">[</span><span class="s1">&#39;username&#39;</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">&#39;admin&#39;</span> <span class="ow">or</span> \
<span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="p">[</span><span class="s1">&#39;password&#39;</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">&#39;secret&#39;</span><span class="p">:</span>
<span class="n">error</span> <span class="o">=</span> <span class="s1">&#39;Invalid credentials&#39;</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">flash</span><span class="p">(</span><span class="s1">&#39;You were successfully logged in&#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;index&#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;login.html&#39;</span><span class="p">,</span> <span class="n">error</span><span class="o">=</span><span class="n">error</span><span class="p">)</span>
</pre></div>
</div>
<p>And here is the <code class="file docutils literal notranslate"><span class="pre">layout.html</span></code> template which does the magic:</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">title</span><span class="p">&gt;</span>My Application<span class="p">&lt;/</span><span class="nt">title</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">with</span> <span class="nv">messages</span> <span class="o">=</span> <span class="nv">get_flashed_messages</span><span class="o">()</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">messages</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">flashes</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">message</span> <span class="k">in</span> <span class="nv">messages</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">message</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="cp">{%</span> <span class="k">endwith</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">body</span> <span class="cp">%}{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>Here is the <code class="file docutils literal notranslate"><span class="pre">index.html</span></code> template which inherits from <code class="file docutils literal notranslate"><span class="pre">layout.html</span></code>:</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">body</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>Overview<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="p">&gt;</span>Do you want to <span class="p">&lt;</span><span class="nt">a</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;login&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>log in?<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>
</pre></div>
</div>
<p>And here is the <code class="file docutils literal notranslate"><span class="pre">login.html</span></code> template which also inherits from
<code class="file docutils literal notranslate"><span class="pre">layout.html</span></code>:</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">body</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">h1</span><span class="p">&gt;</span>Login<span class="p">&lt;/</span><span class="nt">h1</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">error</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">p</span> <span class="na">class</span><span class="o">=</span><span class="s">error</span><span class="p">&gt;&lt;</span><span class="nt">strong</span><span class="p">&gt;</span>Error:<span class="p">&lt;/</span><span class="nt">strong</span><span class="p">&gt;</span> <span class="cp">{{</span> <span class="nv">error</span> <span class="cp">}}</span>
<span class="cp">{%</span> <span class="k">endif</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="p">&lt;</span><span class="nt">dt</span><span class="p">&gt;</span>Username:
<span class="p">&lt;</span><span class="nt">dd</span><span class="p">&gt;&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">text</span> <span class="na">name</span><span class="o">=</span><span class="s">username</span> <span class="na">value</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span>
<span class="nv">request.form.username</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">dt</span><span class="p">&gt;</span>Password:
<span class="p">&lt;</span><span class="nt">dd</span><span class="p">&gt;&lt;</span><span class="nt">input</span> <span class="na">type</span><span class="o">=</span><span class="s">password</span> <span class="na">name</span><span class="o">=</span><span class="s">password</span><span class="p">&gt;</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">Login</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">form</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
</pre></div>
</div>
</section>
<section id="flashing-with-categories">
<h2>Flashing With Categories<a class="headerlink" href="#flashing-with-categories" title="Link to this heading"></a></h2>
<details class="changelog">
<summary>Changelog</summary><div class="versionadded">
<p><span class="versionmodified added">Added in version 0.3.</span></p>
</div>
</details><p>It is also possible to provide categories when flashing a message. The
default category if nothing is provided is <code class="docutils literal notranslate"><span class="pre">'message'</span></code>. Alternative
categories can be used to give the user better feedback. For example
error messages could be displayed with a red background.</p>
<p>To flash a message with a different category, just use the second argument
to the <a class="reference internal" href="../api.html#flask.flash" title="flask.flash"><code class="xref py py-func docutils literal notranslate"><span class="pre">flash()</span></code></a> function:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">flash</span><span class="p">(</span><span class="s1">&#39;Invalid password provided&#39;</span><span class="p">,</span> <span class="s1">&#39;error&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Inside the template you then have to tell the
<a class="reference internal" href="../api.html#flask.get_flashed_messages" title="flask.get_flashed_messages"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_flashed_messages()</span></code></a> function to also return the
categories. The loop looks slightly different in that situation then:</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">with</span> <span class="nv">messages</span> <span class="o">=</span> <span class="nv">get_flashed_messages</span><span class="o">(</span><span class="nv">with_categories</span><span class="o">=</span><span class="kp">true</span><span class="o">)</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">messages</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">flashes</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">for</span> <span class="nv">category</span><span class="o">,</span> <span class="nv">message</span> <span class="k">in</span> <span class="nv">messages</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">li</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">category</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span><span class="cp">{{</span> <span class="nv">message</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="cp">{%</span> <span class="k">endwith</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>This is just one example of how to render these flashed messages. One
might also use the category to add a prefix such as
<code class="docutils literal notranslate"><span class="pre">&lt;strong&gt;Error:&lt;/strong&gt;</span></code> to the message.</p>
</section>
<section id="filtering-flash-messages">
<h2>Filtering Flash Messages<a class="headerlink" href="#filtering-flash-messages" title="Link to this heading"></a></h2>
<details class="changelog">
<summary>Changelog</summary><div class="versionadded">
<p><span class="versionmodified added">Added in version 0.9.</span></p>
</div>
</details><p>Optionally you can pass a list of categories which filters the results of
<a class="reference internal" href="../api.html#flask.get_flashed_messages" title="flask.get_flashed_messages"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_flashed_messages()</span></code></a>. This is useful if you wish to
render each category in a separate block.</p>
<div class="highlight-html+jinja notranslate"><div class="highlight"><pre><span></span><span class="cp">{%</span> <span class="k">with</span> <span class="nv">errors</span> <span class="o">=</span> <span class="nv">get_flashed_messages</span><span class="o">(</span><span class="nv">category_filter</span><span class="o">=[</span><span class="s2">&quot;error&quot;</span><span class="o">])</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">if</span> <span class="nv">errors</span> <span class="cp">%}</span>
<span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;alert-message block-message error&quot;</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">a</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;close&quot;</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;#&quot;</span><span class="p">&gt;</span>×<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">ul</span><span class="p">&gt;</span>
<span class="cp">{%</span>- <span class="k">for</span> <span class="nv">msg</span> <span class="k">in</span> <span class="nv">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">msg</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="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
<span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">endwith</span> <span class="cp">%}</span>
</pre></div>
</div>
</section>
<section id="ajax-with-jquery">
<h1>AJAX with jQuery<a class="headerlink" href="#ajax-with-jquery" title="Link to this heading"></a></h1>
<p>Obsolete, see <a class="reference internal" href="javascript.html"><span class="doc">JavaScript, fetch, and JSON</span></a> instead.</p>
</section>
@ -193,32 +48,16 @@ render each category in a separate block.</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"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Message Flashing</a><ul>
<li><a class="reference internal" href="#simple-flashing">Simple Flashing</a></li>
<li><a class="reference internal" href="#flashing-with-categories">Flashing With Categories</a></li>
<li><a class="reference internal" href="#filtering-flash-messages">Filtering Flash Messages</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="templateinheritance.html" title="previous chapter">Template Inheritance</a>
<li>Next: <a href="javascript.html" title="next chapter">JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
@ -240,4 +79,4 @@ render each category in a separate block.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Patterns for Flask &#8212; Flask Documentation (3.2.x)</title>
<title>Lazily Loading Views &#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="Large Applications as Packages" href="packages.html" />
<link rel="prev" title="Working with the Shell" href="../shell.html" />
<link rel="next" title="MongoDB with MongoEngine" href="mongoengine.html" />
<link rel="prev" title="JavaScript, fetch, and JSON" href="javascript.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,153 +28,126 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="packages.html" title="Large Applications as Packages"
<a href="mongoengine.html" title="MongoDB with MongoEngine"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../shell.html" title="Working with the Shell"
<a href="javascript.html" title="JavaScript, fetch, and JSON"
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-this"><a href="">Patterns for Flask</a></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="">Lazily Loading Views</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="patterns-for-flask">
<h1>Patterns for Flask<a class="headerlink" href="#patterns-for-flask" title="Link to this heading"></a></h1>
<p>Certain features and interactions are common enough that you will find
them in most web applications. For example, many applications use a
relational database and user authentication. They will open a database
connection at the beginning of the request and get the information for
the logged in user. At the end of the request, the database connection
is closed.</p>
<p>These types of patterns may be a bit outside the scope of Flask itself,
but Flask makes it easy to implement them. Some common patterns are
collected in the following pages.</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="packages.html">Large Applications as Packages</a><ul>
<li class="toctree-l2"><a class="reference internal" href="packages.html#simple-packages">Simple Packages</a></li>
<li class="toctree-l2"><a class="reference internal" href="packages.html#working-with-blueprints">Working with Blueprints</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="appfactories.html">Application Factories</a><ul>
<li class="toctree-l2"><a class="reference internal" href="appfactories.html#basic-factories">Basic Factories</a></li>
<li class="toctree-l2"><a class="reference internal" href="appfactories.html#factories-extensions">Factories &amp; Extensions</a></li>
<li class="toctree-l2"><a class="reference internal" href="appfactories.html#using-applications">Using Applications</a></li>
<li class="toctree-l2"><a class="reference internal" href="appfactories.html#factory-improvements">Factory Improvements</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="appdispatch.html">Application Dispatching</a><ul>
<li class="toctree-l2"><a class="reference internal" href="appdispatch.html#working-with-this-document">Working with this Document</a></li>
<li class="toctree-l2"><a class="reference internal" href="appdispatch.html#combining-applications">Combining Applications</a></li>
<li class="toctree-l2"><a class="reference internal" href="appdispatch.html#dispatch-by-subdomain">Dispatch by Subdomain</a></li>
<li class="toctree-l2"><a class="reference internal" href="appdispatch.html#dispatch-by-path">Dispatch by Path</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="urlprocessors.html">Using URL Processors</a><ul>
<li class="toctree-l2"><a class="reference internal" href="urlprocessors.html#internationalized-application-urls">Internationalized Application URLs</a></li>
<li class="toctree-l2"><a class="reference internal" href="urlprocessors.html#internationalized-blueprint-urls">Internationalized Blueprint URLs</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="sqlite3.html">Using SQLite 3 with Flask</a><ul>
<li class="toctree-l2"><a class="reference internal" href="sqlite3.html#connect-on-demand">Connect on Demand</a></li>
<li class="toctree-l2"><a class="reference internal" href="sqlite3.html#easy-querying">Easy Querying</a></li>
<li class="toctree-l2"><a class="reference internal" href="sqlite3.html#initial-schemas">Initial Schemas</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="sqlalchemy.html">SQLAlchemy in Flask</a><ul>
<li class="toctree-l2"><a class="reference internal" href="sqlalchemy.html#flask-sqlalchemy-extension">Flask-SQLAlchemy Extension</a></li>
<li class="toctree-l2"><a class="reference internal" href="sqlalchemy.html#declarative">Declarative</a></li>
<li class="toctree-l2"><a class="reference internal" href="sqlalchemy.html#manual-object-relational-mapping">Manual Object Relational Mapping</a></li>
<li class="toctree-l2"><a class="reference internal" href="sqlalchemy.html#sql-abstraction-layer">SQL Abstraction Layer</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="fileuploads.html">Uploading Files</a><ul>
<li class="toctree-l2"><a class="reference internal" href="fileuploads.html#a-gentle-introduction">A Gentle Introduction</a></li>
<li class="toctree-l2"><a class="reference internal" href="fileuploads.html#improving-uploads">Improving Uploads</a></li>
<li class="toctree-l2"><a class="reference internal" href="fileuploads.html#upload-progress-bars">Upload Progress Bars</a></li>
<li class="toctree-l2"><a class="reference internal" href="fileuploads.html#an-easier-solution">An Easier Solution</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="caching.html">Caching</a></li>
<li class="toctree-l1"><a class="reference internal" href="viewdecorators.html">View Decorators</a><ul>
<li class="toctree-l2"><a class="reference internal" href="viewdecorators.html#login-required-decorator">Login Required Decorator</a></li>
<li class="toctree-l2"><a class="reference internal" href="viewdecorators.html#caching-decorator">Caching Decorator</a></li>
<li class="toctree-l2"><a class="reference internal" href="viewdecorators.html#templating-decorator">Templating Decorator</a></li>
<li class="toctree-l2"><a class="reference internal" href="viewdecorators.html#endpoint-decorator">Endpoint Decorator</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="wtforms.html">Form Validation with WTForms</a><ul>
<li class="toctree-l2"><a class="reference internal" href="wtforms.html#the-forms">The Forms</a></li>
<li class="toctree-l2"><a class="reference internal" href="wtforms.html#in-the-view">In the View</a></li>
<li class="toctree-l2"><a class="reference internal" href="wtforms.html#forms-in-templates">Forms in Templates</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="templateinheritance.html">Template Inheritance</a><ul>
<li class="toctree-l2"><a class="reference internal" href="templateinheritance.html#base-template">Base Template</a></li>
<li class="toctree-l2"><a class="reference internal" href="templateinheritance.html#child-template">Child Template</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="flashing.html">Message Flashing</a><ul>
<li class="toctree-l2"><a class="reference internal" href="flashing.html#simple-flashing">Simple Flashing</a></li>
<li class="toctree-l2"><a class="reference internal" href="flashing.html#flashing-with-categories">Flashing With Categories</a></li>
<li class="toctree-l2"><a class="reference internal" href="flashing.html#filtering-flash-messages">Filtering Flash Messages</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="javascript.html">JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON</a><ul>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#rendering-templates">Rendering Templates</a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#generating-urls">Generating URLs</a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#making-a-request-with-fetch">Making a Request with <code class="docutils literal notranslate"><span class="pre">fetch</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#following-redirects">Following Redirects</a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#replacing-content">Replacing Content</a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#return-json-from-views">Return JSON from Views</a></li>
<li class="toctree-l2"><a class="reference internal" href="javascript.html#receiving-json-in-views">Receiving JSON in Views</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="lazyloading.html">Lazily Loading Views</a><ul>
<li class="toctree-l2"><a class="reference internal" href="lazyloading.html#converting-to-centralized-url-map">Converting to Centralized URL Map</a></li>
<li class="toctree-l2"><a class="reference internal" href="lazyloading.html#loading-late">Loading Late</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="mongoengine.html">MongoDB with MongoEngine</a><ul>
<li class="toctree-l2"><a class="reference internal" href="mongoengine.html#configuration">Configuration</a></li>
<li class="toctree-l2"><a class="reference internal" href="mongoengine.html#mapping-documents">Mapping Documents</a></li>
<li class="toctree-l2"><a class="reference internal" href="mongoengine.html#creating-data">Creating Data</a></li>
<li class="toctree-l2"><a class="reference internal" href="mongoengine.html#queries">Queries</a></li>
<li class="toctree-l2"><a class="reference internal" href="mongoengine.html#documentation">Documentation</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="favicon.html">Adding a favicon</a><ul>
<li class="toctree-l2"><a class="reference internal" href="favicon.html#see-also">See also</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="streaming.html">Streaming Contents</a><ul>
<li class="toctree-l2"><a class="reference internal" href="streaming.html#basic-usage">Basic Usage</a></li>
<li class="toctree-l2"><a class="reference internal" href="streaming.html#streaming-from-templates">Streaming from Templates</a></li>
<li class="toctree-l2"><a class="reference internal" href="streaming.html#streaming-with-context">Streaming with Context</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="deferredcallbacks.html">Deferred Request Callbacks</a></li>
<li class="toctree-l1"><a class="reference internal" href="methodoverrides.html">Adding HTTP Method Overrides</a></li>
<li class="toctree-l1"><a class="reference internal" href="requestchecksum.html">Request Content Checksums</a></li>
<li class="toctree-l1"><a class="reference internal" href="celery.html">Background Tasks with Celery</a><ul>
<li class="toctree-l2"><a class="reference internal" href="celery.html#install">Install</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#integrate-celery-with-flask">Integrate Celery with Flask</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#application-factory">Application Factory</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#defining-tasks">Defining Tasks</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#calling-tasks">Calling Tasks</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#getting-results">Getting Results</a></li>
<li class="toctree-l2"><a class="reference internal" href="celery.html#passing-data-to-tasks">Passing Data to Tasks</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="subclassing.html">Subclassing Flask</a></li>
<li class="toctree-l1"><a class="reference internal" href="singlepageapplications.html">Single-Page Applications</a></li>
</ul>
<section id="lazily-loading-views">
<h1>Lazily Loading Views<a class="headerlink" href="#lazily-loading-views" title="Link to this heading"></a></h1>
<p>Flask is usually used with the decorators. Decorators are simple and you
have the URL right next to the function that is called for that specific
URL. However there is a downside to this approach: it means all your code
that uses decorators has to be imported upfront or Flask will never
actually find your function.</p>
<p>This can be a problem if your application has to import quick. It might
have to do that on systems like Googles App Engine or other systems. So
if you suddenly notice that your application outgrows this approach you
can fall back to a centralized URL mapping.</p>
<p>The system that enables having a central URL map is the
<a class="reference internal" href="../api.html#flask.Flask.add_url_rule" title="flask.Flask.add_url_rule"><code class="xref py py-meth docutils literal notranslate"><span class="pre">add_url_rule()</span></code></a> function. Instead of using decorators,
you have a file that sets up the application with all URLs.</p>
<section id="converting-to-centralized-url-map">
<h2>Converting to Centralized URL Map<a class="headerlink" href="#converting-to-centralized-url-map" title="Link to this heading"></a></h2>
<p>Imagine the current application looks somewhat like this:</p>
<div class="highlight-default 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="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">index</span><span class="p">():</span>
<span class="k">pass</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/user/&lt;username&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user</span><span class="p">(</span><span class="n">username</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>Then, with the centralized approach you would have one file with the views
(<code class="file docutils literal notranslate"><span class="pre">views.py</span></code>) but without any decorator:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">():</span>
<span class="k">pass</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user</span><span class="p">(</span><span class="n">username</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>And then a file that sets up an application which maps the functions to
URLs:</p>
<div class="highlight-default 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="kn">from</span><span class="w"> </span><span class="nn">yourapplication</span><span class="w"> </span><span class="kn">import</span> <span class="n">views</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="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="n">view_func</span><span class="o">=</span><span class="n">views</span><span class="o">.</span><span class="n">index</span><span class="p">)</span>
<span class="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span><span class="s1">&#39;/user/&lt;username&gt;&#39;</span><span class="p">,</span> <span class="n">view_func</span><span class="o">=</span><span class="n">views</span><span class="o">.</span><span class="n">user</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="loading-late">
<h2>Loading Late<a class="headerlink" href="#loading-late" title="Link to this heading"></a></h2>
<p>So far we only split up the views and the routing, but the module is still
loaded upfront. The trick is to actually load the view function as needed.
This can be accomplished with a helper class that behaves just like a
function but internally imports the real function on first use:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">werkzeug.utils</span><span class="w"> </span><span class="kn">import</span> <span class="n">import_string</span><span class="p">,</span> <span class="n">cached_property</span>
<span class="k">class</span><span class="w"> </span><span class="nc">LazyView</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">import_name</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="vm">__module__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__name__</span> <span class="o">=</span> <span class="n">import_name</span><span class="o">.</span><span class="n">rsplit</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">import_name</span> <span class="o">=</span> <span class="n">import_name</span>
<span class="nd">@cached_property</span>
<span class="k">def</span><span class="w"> </span><span class="nf">view</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="n">import_string</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">import_name</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</pre></div>
</div>
<p>Whats important here is is that <code class="code docutils literal notranslate"><span class="pre">__module__</span></code> and <code class="code docutils literal notranslate"><span class="pre">__name__</span></code> are properly
set. This is used by Flask internally to figure out how to name the
URL rules in case you dont provide a name for the rule yourself.</p>
<p>Then you can define your central place to combine the views like this:</p>
<div class="highlight-default 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="kn">from</span><span class="w"> </span><span class="nn">yourapplication.helpers</span><span class="w"> </span><span class="kn">import</span> <span class="n">LazyView</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="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span>
<span class="n">view_func</span><span class="o">=</span><span class="n">LazyView</span><span class="p">(</span><span class="s1">&#39;yourapplication.views.index&#39;</span><span class="p">))</span>
<span class="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span><span class="s1">&#39;/user/&lt;username&gt;&#39;</span><span class="p">,</span>
<span class="n">view_func</span><span class="o">=</span><span class="n">LazyView</span><span class="p">(</span><span class="s1">&#39;yourapplication.views.user&#39;</span><span class="p">))</span>
</pre></div>
</div>
<p>You can further optimize this in terms of amount of keystrokes needed to
write this by having a function that calls into
<a class="reference internal" href="../api.html#flask.Flask.add_url_rule" title="flask.Flask.add_url_rule"><code class="xref py py-meth docutils literal notranslate"><span class="pre">add_url_rule()</span></code></a> by prefixing a string with the project
name and a dot, and by wrapping <code class="code docutils literal notranslate"><span class="pre">view_func</span></code> in a <code class="code docutils literal notranslate"><span class="pre">LazyView</span></code> as needed.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">url</span><span class="p">(</span><span class="n">import_name</span><span class="p">,</span> <span class="n">url_rules</span><span class="o">=</span><span class="p">[],</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
<span class="n">view</span> <span class="o">=</span> <span class="n">LazyView</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;yourapplication.</span><span class="si">{</span><span class="n">import_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">url_rule</span> <span class="ow">in</span> <span class="n">url_rules</span><span class="p">:</span>
<span class="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span><span class="n">url_rule</span><span class="p">,</span> <span class="n">view_func</span><span class="o">=</span><span class="n">view</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
<span class="c1"># add a single route to the index view</span>
<span class="n">url</span><span class="p">(</span><span class="s1">&#39;views.index&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;/&#39;</span><span class="p">])</span>
<span class="c1"># add two routes to a single function endpoint</span>
<span class="n">url_rules</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;/user/&#39;</span><span class="p">,</span><span class="s1">&#39;/user/&lt;username&gt;&#39;</span><span class="p">]</span>
<span class="n">url</span><span class="p">(</span><span class="s1">&#39;views.user&#39;</span><span class="p">,</span> <span class="n">url_rules</span><span class="p">)</span>
</pre></div>
</div>
<p>One thing to keep in mind is that before and after request handlers have
to be in a file that is imported upfront to work properly on the first
request. The same goes for any kind of remaining decorator.</p>
</section>
</section>
@ -185,18 +158,30 @@ collected in the following pages.</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"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Lazily Loading Views</a><ul>
<li><a class="reference internal" href="#converting-to-centralized-url-map">Converting to Centralized URL Map</a></li>
<li><a class="reference internal" href="#loading-late">Loading Late</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li>Previous: <a href="../shell.html" title="previous chapter">Working with the Shell</a>
<li>Next: <a href="packages.html" title="next chapter">Large Applications as Packages</a>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="javascript.html" title="previous chapter">JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON</a>
<li>Next: <a href="mongoengine.html" title="next chapter">MongoDB with MongoEngine</a></ul>
</li>
</ul>
</li>
</ul>
@ -219,4 +204,4 @@ collected in the following pages.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>JavaScript, fetch, and JSON &#8212; Flask Documentation (3.2.x)</title>
<title>Adding HTTP Method Overrides &#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="Lazily Loading Views" href="lazyloading.html" />
<link rel="prev" title="Message Flashing" href="flashing.html" />
<link rel="next" title="Request Content Checksums" href="requestchecksum.html" />
<link rel="prev" title="Deferred Request Callbacks" href="deferredcallbacks.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,228 +28,62 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="lazyloading.html" title="Lazily Loading Views"
<a href="requestchecksum.html" title="Request Content Checksums"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="flashing.html" title="Message Flashing"
<a href="deferredcallbacks.html" title="Deferred Request Callbacks"
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="">JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON</a></li>
<li class="nav-item nav-item-this"><a href="">Adding HTTP Method Overrides</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="javascript-fetch-and-json">
<h1>JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON<a class="headerlink" href="#javascript-fetch-and-json" title="Link to this heading"></a></h1>
<p>You may want to make your HTML page dynamic, by changing data without
reloading the entire page. Instead of submitting an HTML <code class="docutils literal notranslate"><span class="pre">&lt;form&gt;</span></code> and
performing a redirect to re-render the template, you can add
<a class="reference external" href="https://developer.mozilla.org/Web/JavaScript">JavaScript</a> that calls <a class="reference external" href="https://developer.mozilla.org/Web/API/Fetch_API"><code class="docutils literal notranslate"><span class="pre">fetch()</span></code></a> and replaces content on the page.</p>
<p><a class="reference external" href="https://developer.mozilla.org/Web/API/Fetch_API"><code class="docutils literal notranslate"><span class="pre">fetch()</span></code></a> is the modern, built-in JavaScript solution to making
requests from a page. You may have heard of other “AJAX” methods and
libraries, such as <a class="reference external" href="https://developer.mozilla.org/Web/API/XMLHttpRequest"><code class="docutils literal notranslate"><span class="pre">XMLHttpRequest()</span></code></a> or <a class="reference external" href="https://jquery.com/">jQuery</a>. These are no longer needed in
modern browsers, although you may choose to use them or another library
depending on your applications requirements. These docs will only focus
on built-in JavaScript features.</p>
<section id="rendering-templates">
<h2>Rendering Templates<a class="headerlink" href="#rendering-templates" title="Link to this heading"></a></h2>
<p>It is important to understand the difference between templates and
JavaScript. Templates are rendered on the server, before the response is
sent to the users browser. JavaScript runs in the users browser, after
the template is rendered and sent. Therefore, it is impossible to use
JavaScript to affect how the Jinja template is rendered, but it is
possible to render data into the JavaScript that will run.</p>
<p>To provide data to JavaScript when rendering the template, use the
<a class="reference external" href="https://jinja.palletsprojects.com/en/stable/templates/#jinja-filters.tojson" title="(in Jinja v3.1.x)"><code class="xref py py-func docutils literal notranslate"><span class="pre">tojson()</span></code></a> filter in a <code class="docutils literal notranslate"><span class="pre">&lt;script&gt;</span></code> block. This will
convert the data to a valid JavaScript object, and ensure that any
unsafe HTML characters are rendered safely. If you do not use the
<code class="docutils literal notranslate"><span class="pre">tojson</span></code> filter, you will get a <code class="docutils literal notranslate"><span class="pre">SyntaxError</span></code> in the browser
console.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">data</span> <span class="o">=</span> <span class="n">generate_report</span><span class="p">()</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">&quot;report.html&quot;</span><span class="p">,</span> <span class="n">chart_data</span><span class="o">=</span><span class="n">data</span><span class="p">)</span>
</pre></div>
</div>
<div class="highlight-jinja notranslate"><div class="highlight"><pre><span></span><span class="x">&lt;script&gt;</span>
<span class="x"> const chart_data = </span><span class="cp">{{</span> <span class="nv">chart_data</span><span class="o">|</span><span class="nf">tojson</span> <span class="cp">}}</span>
<span class="x"> chartLib.makeChart(chart_data)</span>
<span class="x">&lt;/script&gt;</span>
</pre></div>
</div>
<p>A less common pattern is to add the data to a <code class="docutils literal notranslate"><span class="pre">data-</span></code> attribute on an
HTML tag. In this case, you must use single quotes around the value, not
double quotes, otherwise you will produce invalid or unsafe HTML.</p>
<div class="highlight-jinja notranslate"><div class="highlight"><pre><span></span><span class="x">&lt;div data-chart=&#39;</span><span class="cp">{{</span> <span class="nv">chart_data</span><span class="o">|</span><span class="nf">tojson</span> <span class="cp">}}</span><span class="x">&#39;&gt;&lt;/div&gt;</span>
</pre></div>
</div>
</section>
<section id="generating-urls">
<h2>Generating URLs<a class="headerlink" href="#generating-urls" title="Link to this heading"></a></h2>
<p>The other way to get data from the server to JavaScript is to make a
request for it. First, you need to know the URL to request.</p>
<p>The simplest way to generate URLs is to continue to use
<a class="reference internal" href="../api.html#flask.url_for" title="flask.url_for"><code class="xref py py-func docutils literal notranslate"><span class="pre">url_for()</span></code></a> when rendering the template. For example:</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">const</span><span class="w"> </span><span class="nx">user_url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">url_for</span><span class="p">(</span><span class="s2">&quot;user&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">id</span><span class="o">=</span><span class="nx">current_user</span><span class="p">.</span><span class="nx">id</span><span class="p">)</span><span class="o">|</span><span class="nx">tojson</span><span class="w"> </span><span class="p">}}</span>
<span class="nx">fetch</span><span class="p">(</span><span class="nx">user_url</span><span class="p">).</span><span class="nx">then</span><span class="p">(...)</span>
</pre></div>
</div>
<p>However, you might need to generate a URL based on information you only
know in JavaScript. As discussed above, JavaScript runs in the users
browser, not as part of the template rendering, so you cant use
<code class="docutils literal notranslate"><span class="pre">url_for</span></code> at that point.</p>
<p>In this case, you need to know the “root URL” under which your
application is served. In simple setups, this is <code class="docutils literal notranslate"><span class="pre">/</span></code>, but it might
also be something else, like <code class="docutils literal notranslate"><span class="pre">https://example.com/myapp/</span></code>.</p>
<p>A simple way to tell your JavaScript code about this root is to set it
as a global variable when rendering the template. Then you can use it
when generating URLs from JavaScript.</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">const</span><span class="w"> </span><span class="nx">SCRIPT_ROOT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">request</span><span class="p">.</span><span class="nx">script_root</span><span class="o">|</span><span class="nx">tojson</span><span class="w"> </span><span class="p">}}</span>
<span class="kd">let</span><span class="w"> </span><span class="nx">user_id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="c1">// do something to get a user id from the page</span>
<span class="kd">let</span><span class="w"> </span><span class="nx">user_url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sb">`</span><span class="si">${</span><span class="nx">SCRIPT_ROOT</span><span class="si">}</span><span class="sb">/user/</span><span class="si">${</span><span class="nx">user_id</span><span class="si">}</span><span class="sb">`</span>
<span class="nx">fetch</span><span class="p">(</span><span class="nx">user_url</span><span class="p">).</span><span class="nx">then</span><span class="p">(...)</span>
</pre></div>
</div>
</section>
<section id="making-a-request-with-fetch">
<h2>Making a Request with <code class="docutils literal notranslate"><span class="pre">fetch</span></code><a class="headerlink" href="#making-a-request-with-fetch" title="Link to this heading"></a></h2>
<p><a class="reference external" href="https://developer.mozilla.org/Web/API/Fetch_API"><code class="docutils literal notranslate"><span class="pre">fetch()</span></code></a> takes two arguments, a URL and an object with other options,
and returns a <a class="reference external" href="https://developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/Promise"><code class="docutils literal notranslate"><span class="pre">Promise</span></code></a>. We wont cover all the available options, and
will only use <code class="docutils literal notranslate"><span class="pre">then()</span></code> on the promise, not other callbacks or
<code class="docutils literal notranslate"><span class="pre">await</span></code> syntax. Read the linked MDN docs for more information about
those features.</p>
<p>By default, the GET method is used. If the response contains JSON, it
can be used with a <code class="docutils literal notranslate"><span class="pre">then()</span></code> callback chain.</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">const</span><span class="w"> </span><span class="nx">room_url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">url_for</span><span class="p">(</span><span class="s2">&quot;room_detail&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">id</span><span class="o">=</span><span class="nx">room</span><span class="p">.</span><span class="nx">id</span><span class="p">)</span><span class="o">|</span><span class="nx">tojson</span><span class="w"> </span><span class="p">}}</span>
<span class="nx">fetch</span><span class="p">(</span><span class="nx">room_url</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">response</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">())</span>
<span class="w"> </span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">data</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// data is a parsed JSON object</span>
<span class="w"> </span><span class="p">})</span>
</pre></div>
</div>
<p>To send data, use a data method such as POST, and pass the <code class="docutils literal notranslate"><span class="pre">body</span></code>
option. The most common types for data are form data or JSON data.</p>
<p>To send form data, pass a populated <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/API/FormData"><code class="docutils literal notranslate"><span class="pre">FormData</span></code></a> object. This uses the
same format as an HTML form, and would be accessed with <code class="docutils literal notranslate"><span class="pre">request.form</span></code>
in a Flask view.</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">let</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">FormData</span><span class="p">()</span>
<span class="nx">data</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="s2">&quot;name&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;Flask Room&quot;</span><span class="p">)</span>
<span class="nx">data</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="s2">&quot;description&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;Talk about Flask here.&quot;</span><span class="p">)</span>
<span class="nx">fetch</span><span class="p">(</span><span class="nx">room_url</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;method&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;POST&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;body&quot;</span><span class="o">:</span><span class="w"> </span><span class="nx">data</span><span class="p">,</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(...)</span>
</pre></div>
</div>
<p>In general, prefer sending request data as form data, as would be used
when submitting an HTML form. JSON can represent more complex data, but
unless you need that its better to stick with the simpler format. When
sending JSON data, the <code class="docutils literal notranslate"><span class="pre">Content-Type:</span> <span class="pre">application/json</span></code> header must be
sent as well, otherwise Flask will return a 400 error.</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">let</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;name&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Flask Room&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;description&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;Talk about Flask here.&quot;</span><span class="p">,</span>
<span class="p">}</span>
<span class="nx">fetch</span><span class="p">(</span><span class="nx">room_url</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;method&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;POST&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;headers&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="s2">&quot;Content-Type&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;application/json&quot;</span><span class="p">},</span>
<span class="w"> </span><span class="s2">&quot;body&quot;</span><span class="o">:</span><span class="w"> </span><span class="nb">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">data</span><span class="p">),</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(...)</span>
</pre></div>
</div>
</section>
<section id="following-redirects">
<h2>Following Redirects<a class="headerlink" href="#following-redirects" title="Link to this heading"></a></h2>
<p>A response might be a redirect, for example if you logged in with
JavaScript instead of a traditional HTML form, and your view returned
a redirect instead of JSON. JavaScript requests do follow redirects, but
they dont change the page. If you want to make the page change you can
inspect the response and apply the redirect manually.</p>
<div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="nx">fetch</span><span class="p">(</span><span class="s2">&quot;/login&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="s2">&quot;body&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">...}).</span><span class="nx">then</span><span class="p">(</span>
<span class="w"> </span><span class="nx">response</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">response</span><span class="p">.</span><span class="nx">redirected</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">response</span><span class="p">.</span><span class="nx">url</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">showLoginError</span><span class="p">()</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">)</span>
</pre></div>
</div>
</section>
<section id="replacing-content">
<h2>Replacing Content<a class="headerlink" href="#replacing-content" title="Link to this heading"></a></h2>
<p>A response might be new HTML, either a new section of the page to add or
replace, or an entirely new page. In general, if youre returning the
entire page, it would be better to handle that with a redirect as shown
in the previous section. The following example shows how to replace a
<code class="docutils literal notranslate"><span class="pre">&lt;div&gt;</span></code> with the HTML returned by a request.</p>
<div class="highlight-html notranslate"><div class="highlight"><pre><span></span><span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">&quot;geology-fact&quot;</span><span class="p">&gt;</span>
{{ include &quot;geology_fact.html&quot; }}
<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">script</span><span class="p">&gt;</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">geology_url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">url_for</span><span class="p">(</span><span class="s2">&quot;geology_fact&quot;</span><span class="p">)</span><span class="o">|</span><span class="nx">tojson</span><span class="w"> </span><span class="p">}}</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">geology_div</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">&quot;geology-fact&quot;</span><span class="p">)</span>
<span class="w"> </span><span class="nx">fetch</span><span class="p">(</span><span class="nx">geology_url</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">response</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">response</span><span class="p">.</span><span class="nx">text</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">text</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">geology_div</span><span class="p">.</span><span class="nx">innerHTML</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">text</span><span class="p">)</span>
<span class="p">&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</pre></div>
</div>
</section>
<section id="return-json-from-views">
<h2>Return JSON from Views<a class="headerlink" href="#return-json-from-views" title="Link to this heading"></a></h2>
<p>To return a JSON object from your API view, you can directly return a
dict from the view. It will be serialized to JSON automatically.</p>
<div class="highlight-python 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="s2">&quot;/user/&lt;int:id&gt;&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user_detail</span><span class="p">(</span><span class="nb">id</span><span class="p">):</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">get_or_404</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span>
<span class="k">return</span> <span class="p">{</span>
<span class="s2">&quot;username&quot;</span><span class="p">:</span> <span class="n">User</span><span class="o">.</span><span class="n">username</span><span class="p">,</span>
<span class="s2">&quot;email&quot;</span><span class="p">:</span> <span class="n">User</span><span class="o">.</span><span class="n">email</span><span class="p">,</span>
<span class="s2">&quot;picture&quot;</span><span class="p">:</span> <span class="n">url_for</span><span class="p">(</span><span class="s2">&quot;static&quot;</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="sa">f</span><span class="s2">&quot;users/</span><span class="si">{</span><span class="nb">id</span><span class="si">}</span><span class="s2">/profile.png&quot;</span><span class="p">),</span>
<span class="p">}</span>
</pre></div>
</div>
<p>If you want to return another JSON type, use the
<a class="reference internal" href="../api.html#flask.json.jsonify" title="flask.json.jsonify"><code class="xref py py-func docutils literal notranslate"><span class="pre">jsonify()</span></code></a> function, which creates a response object
with the given data serialized to JSON.</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">jsonify</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/users&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user_list</span><span class="p">():</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">order_by</span><span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">([</span><span class="n">u</span><span class="o">.</span><span class="n">to_json</span><span class="p">()</span> <span class="k">for</span> <span class="n">u</span> <span class="ow">in</span> <span class="n">users</span><span class="p">])</span>
</pre></div>
</div>
<p>It is usually not a good idea to return file data in a JSON response.
JSON cannot represent binary data directly, so it must be base64
encoded, which can be slow, takes more bandwidth to send, and is not as
easy to cache. Instead, serve files using one view, and generate a URL
to the desired file to include in the JSON. Then the client can make a
separate request to get the linked resource after getting the JSON.</p>
</section>
<section id="receiving-json-in-views">
<h2>Receiving JSON in Views<a class="headerlink" href="#receiving-json-in-views" title="Link to this heading"></a></h2>
<p>Use the <a class="reference internal" href="../api.html#flask.Request.json" title="flask.Request.json"><code class="xref py py-attr docutils literal notranslate"><span class="pre">json</span></code></a> property of 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> object to decode the requests body as JSON. If
the body is not valid JSON, or the <code class="docutils literal notranslate"><span class="pre">Content-Type</span></code> header is not set to
<code class="docutils literal notranslate"><span class="pre">application/json</span></code>, a 400 Bad Request error will be raised.</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">request</span>
<section id="adding-http-method-overrides">
<h1>Adding HTTP Method Overrides<a class="headerlink" href="#adding-http-method-overrides" title="Link to this heading"></a></h1>
<p>Some HTTP proxies do not support arbitrary HTTP methods or newer HTTP
methods (such as PATCH). In that case its possible to “proxy” HTTP
methods through another HTTP method in total violation of the protocol.</p>
<p>The way this works is by letting the client do an HTTP POST request and
set the <code class="docutils literal notranslate"><span class="pre">X-HTTP-Method-Override</span></code> header. Then the method is replaced
with the header value before being passed to Flask.</p>
<p>This can be accomplished with an HTTP middleware:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">HTTPMethodOverrideMiddleware</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="n">allowed_methods</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">([</span>
<span class="s1">&#39;GET&#39;</span><span class="p">,</span>
<span class="s1">&#39;HEAD&#39;</span><span class="p">,</span>
<span class="s1">&#39;POST&#39;</span><span class="p">,</span>
<span class="s1">&#39;DELETE&#39;</span><span class="p">,</span>
<span class="s1">&#39;PUT&#39;</span><span class="p">,</span>
<span class="s1">&#39;PATCH&#39;</span><span class="p">,</span>
<span class="s1">&#39;OPTIONS&#39;</span>
<span class="p">])</span>
<span class="n">bodyless_methods</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">([</span><span class="s1">&#39;GET&#39;</span><span class="p">,</span> <span class="s1">&#39;HEAD&#39;</span><span class="p">,</span> <span class="s1">&#39;OPTIONS&#39;</span><span class="p">,</span> <span class="s1">&#39;DELETE&#39;</span><span class="p">])</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">&quot;/user/&lt;int:id&gt;&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user_update</span><span class="p">(</span><span class="nb">id</span><span class="p">):</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">get_or_404</span><span class="p">(</span><span class="nb">id</span><span class="p">)</span>
<span class="n">user</span><span class="o">.</span><span class="n">update_from_json</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">json</span><span class="p">)</span>
<span class="n">db</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
<span class="k">return</span> <span class="n">user</span><span class="o">.</span><span class="n">to_json</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">app</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;HTTP_X_HTTP_METHOD_OVERRIDE&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
<span class="k">if</span> <span class="n">method</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">allowed_methods</span><span class="p">:</span>
<span class="n">environ</span><span class="p">[</span><span class="s1">&#39;REQUEST_METHOD&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">method</span>
<span class="k">if</span> <span class="n">method</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">bodyless_methods</span><span class="p">:</span>
<span class="n">environ</span><span class="p">[</span><span class="s1">&#39;CONTENT_LENGTH&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;0&#39;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
</pre></div>
</div>
<p>To use this with Flask, wrap the app object with the middleware:</p>
<div class="highlight-default 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="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="n">app</span><span class="o">.</span><span class="n">wsgi_app</span> <span class="o">=</span> <span class="n">HTTPMethodOverrideMiddleware</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">wsgi_app</span><span class="p">)</span>
</pre></div>
</div>
</section>
</section>
@ -260,34 +94,20 @@ the body is not valid JSON, or the <code class="docutils literal notranslate"><s
<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="#">JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON</a><ul>
<li><a class="reference internal" href="#rendering-templates">Rendering Templates</a></li>
<li><a class="reference internal" href="#generating-urls">Generating URLs</a></li>
<li><a class="reference internal" href="#making-a-request-with-fetch">Making a Request with <code class="docutils literal notranslate"><span class="pre">fetch</span></code></a></li>
<li><a class="reference internal" href="#following-redirects">Following Redirects</a></li>
<li><a class="reference internal" href="#replacing-content">Replacing Content</a></li>
<li><a class="reference internal" href="#return-json-from-views">Return JSON from Views</a></li>
<li><a class="reference internal" href="#receiving-json-in-views">Receiving JSON in Views</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="flashing.html" title="previous chapter">Message Flashing</a>
<li>Next: <a href="lazyloading.html" title="next chapter">Lazily Loading Views</a></ul>
<li>Previous: <a href="deferredcallbacks.html" title="previous chapter">Deferred Request Callbacks</a>
<li>Next: <a href="requestchecksum.html" title="next chapter">Request Content Checksums</a></ul>
</li>
</ul>
</li>
@ -311,4 +131,4 @@ the body is not valid JSON, or the <code class="docutils literal notranslate"><s
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>AJAX with jQuery &#8212; Flask Documentation (3.2.x)</title>
<title>MongoDB with MongoEngine &#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>
@ -14,7 +14,9 @@
<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="search" title="Search" href="../search.html" />
<link rel="next" title="Adding a favicon" href="favicon.html" />
<link rel="prev" title="Lazily Loading Views" href="lazyloading.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -25,19 +27,114 @@
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="favicon.html" title="Adding a favicon"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="lazyloading.html" title="Lazily Loading Views"
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-this"><a href="">AJAX with jQuery</a></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="">MongoDB with MongoEngine</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="ajax-with-jquery">
<h1>AJAX with jQuery<a class="headerlink" href="#ajax-with-jquery" title="Link to this heading"></a></h1>
<p>Obsolete, see <a class="reference internal" href="javascript.html"><span class="doc">JavaScript, fetch, and JSON</span></a> instead.</p>
<section id="mongodb-with-mongoengine">
<h1>MongoDB with MongoEngine<a class="headerlink" href="#mongodb-with-mongoengine" title="Link to this heading"></a></h1>
<p>Using a document database like MongoDB is a common alternative to
relational SQL databases. This pattern shows how to use
<a class="reference external" href="http://mongoengine.org">MongoEngine</a>, a document mapper library, to integrate with MongoDB.</p>
<p>A running MongoDB server and <a class="reference external" href="https://flask-mongoengine.readthedocs.io">Flask-MongoEngine</a> are required.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip</span> <span class="n">install</span> <span class="n">flask</span><span class="o">-</span><span class="n">mongoengine</span>
</pre></div>
</div>
<section id="configuration">
<h2>Configuration<a class="headerlink" href="#configuration" title="Link to this heading"></a></h2>
<p>Basic setup can be done by defining <code class="docutils literal notranslate"><span class="pre">MONGODB_SETTINGS</span></code> on
<code class="docutils literal notranslate"><span class="pre">app.config</span></code> and creating a <code class="docutils literal notranslate"><span class="pre">MongoEngine</span></code> instance.</p>
<div class="highlight-default 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="kn">from</span><span class="w"> </span><span class="nn">flask_mongoengine</span><span class="w"> </span><span class="kn">import</span> <span class="n">MongoEngine</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="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;MONGODB_SETTINGS&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">&quot;db&quot;</span><span class="p">:</span> <span class="s2">&quot;myapp&quot;</span><span class="p">,</span>
<span class="p">}</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">MongoEngine</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="mapping-documents">
<h2>Mapping Documents<a class="headerlink" href="#mapping-documents" title="Link to this heading"></a></h2>
<p>To declare a model that represents a Mongo document, create a class that
inherits from <code class="docutils literal notranslate"><span class="pre">Document</span></code> and declare each of the fields.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">mongoengine</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">me</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Movie</span><span class="p">(</span><span class="n">me</span><span class="o">.</span><span class="n">Document</span><span class="p">):</span>
<span class="n">title</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">StringField</span><span class="p">(</span><span class="n">required</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">year</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">IntField</span><span class="p">()</span>
<span class="n">rated</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">StringField</span><span class="p">()</span>
<span class="n">director</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">StringField</span><span class="p">()</span>
<span class="n">actors</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">ListField</span><span class="p">()</span>
</pre></div>
</div>
<p>If the document has nested fields, use <code class="docutils literal notranslate"><span class="pre">EmbeddedDocument</span></code> to
defined the fields of the embedded document and
<code class="docutils literal notranslate"><span class="pre">EmbeddedDocumentField</span></code> to declare it on the parent document.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Imdb</span><span class="p">(</span><span class="n">me</span><span class="o">.</span><span class="n">EmbeddedDocument</span><span class="p">):</span>
<span class="n">imdb_id</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">StringField</span><span class="p">()</span>
<span class="n">rating</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">DecimalField</span><span class="p">()</span>
<span class="n">votes</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">IntField</span><span class="p">()</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Movie</span><span class="p">(</span><span class="n">me</span><span class="o">.</span><span class="n">Document</span><span class="p">):</span>
<span class="o">...</span>
<span class="n">imdb</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">EmbeddedDocumentField</span><span class="p">(</span><span class="n">Imdb</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="creating-data">
<h2>Creating Data<a class="headerlink" href="#creating-data" title="Link to this heading"></a></h2>
<p>Instantiate your document class with keyword arguments for the fields.
You can also assign values to the field attributes after instantiation.
Then call <code class="docutils literal notranslate"><span class="pre">doc.save()</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">bttf</span> <span class="o">=</span> <span class="n">Movie</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="s2">&quot;Back To The Future&quot;</span><span class="p">,</span> <span class="n">year</span><span class="o">=</span><span class="mi">1985</span><span class="p">)</span>
<span class="n">bttf</span><span class="o">.</span><span class="n">actors</span> <span class="o">=</span> <span class="p">[</span>
<span class="s2">&quot;Michael J. Fox&quot;</span><span class="p">,</span>
<span class="s2">&quot;Christopher Lloyd&quot;</span>
<span class="p">]</span>
<span class="n">bttf</span><span class="o">.</span><span class="n">imdb</span> <span class="o">=</span> <span class="n">Imdb</span><span class="p">(</span><span class="n">imdb_id</span><span class="o">=</span><span class="s2">&quot;tt0088763&quot;</span><span class="p">,</span> <span class="n">rating</span><span class="o">=</span><span class="mf">8.5</span><span class="p">)</span>
<span class="n">bttf</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</div>
</section>
<section id="queries">
<h2>Queries<a class="headerlink" href="#queries" title="Link to this heading"></a></h2>
<p>Use the class <code class="docutils literal notranslate"><span class="pre">objects</span></code> attribute to make queries. A keyword argument
looks for an equal value on the field.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">bttf</span> <span class="o">=</span> <span class="n">Movie</span><span class="o">.</span><span class="n">objects</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="s2">&quot;Back To The Future&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">get_or_404</span><span class="p">()</span>
</pre></div>
</div>
<p>Query operators may be used by concatenating them with the field name
using a double-underscore. <code class="docutils literal notranslate"><span class="pre">objects</span></code>, and queries returned by
calling it, are iterable.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">some_theron_movie</span> <span class="o">=</span> <span class="n">Movie</span><span class="o">.</span><span class="n">objects</span><span class="p">(</span><span class="n">actors__in</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;Charlize Theron&quot;</span><span class="p">])</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="k">for</span> <span class="n">recents</span> <span class="ow">in</span> <span class="n">Movie</span><span class="o">.</span><span class="n">objects</span><span class="p">(</span><span class="n">year__gte</span><span class="o">=</span><span class="mi">2017</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="n">recents</span><span class="o">.</span><span class="n">title</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="documentation">
<h2>Documentation<a class="headerlink" href="#documentation" title="Link to this heading"></a></h2>
<p>There are many more ways to define and query documents with MongoEngine.
For more information, check out the <a class="reference external" href="http://mongoengine.org">official documentation</a>.</p>
<p>Flask-MongoEngine adds helpful utilities on top of MongoEngine. Check
out their <a class="reference external" href="https://flask-mongoengine.readthedocs.io">documentation</a> as well.</p>
</section>
</section>
@ -48,16 +145,34 @@
<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="#">MongoDB with MongoEngine</a><ul>
<li><a class="reference internal" href="#configuration">Configuration</a></li>
<li><a class="reference internal" href="#mapping-documents">Mapping Documents</a></li>
<li><a class="reference internal" href="#creating-data">Creating Data</a></li>
<li><a class="reference internal" href="#queries">Queries</a></li>
<li><a class="reference internal" href="#documentation">Documentation</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="lazyloading.html" title="previous chapter">Lazily Loading Views</a>
<li>Next: <a href="favicon.html" title="next chapter">Adding a favicon</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
@ -79,4 +194,4 @@
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Lazily Loading Views &#8212; Flask Documentation (3.2.x)</title>
<title>Large Applications as Packages &#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="MongoDB with MongoEngine" href="mongoengine.html" />
<link rel="prev" title="JavaScript, fetch, and JSON" href="javascript.html" />
<link rel="next" title="Application Factories" href="appfactories.html" />
<link rel="prev" title="Patterns for Flask" href="index.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,125 +28,144 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="mongoengine.html" title="MongoDB with MongoEngine"
<a href="appfactories.html" title="Application Factories"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="javascript.html" title="JavaScript, fetch, and JSON"
<a href="index.html" title="Patterns for Flask"
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="">Lazily Loading Views</a></li>
<li class="nav-item nav-item-this"><a href="">Large Applications as Packages</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="lazily-loading-views">
<h1>Lazily Loading Views<a class="headerlink" href="#lazily-loading-views" title="Link to this heading"></a></h1>
<p>Flask is usually used with the decorators. Decorators are simple and you
have the URL right next to the function that is called for that specific
URL. However there is a downside to this approach: it means all your code
that uses decorators has to be imported upfront or Flask will never
actually find your function.</p>
<p>This can be a problem if your application has to import quick. It might
have to do that on systems like Googles App Engine or other systems. So
if you suddenly notice that your application outgrows this approach you
can fall back to a centralized URL mapping.</p>
<p>The system that enables having a central URL map is the
<a class="reference internal" href="../api.html#flask.Flask.add_url_rule" title="flask.Flask.add_url_rule"><code class="xref py py-meth docutils literal notranslate"><span class="pre">add_url_rule()</span></code></a> function. Instead of using decorators,
you have a file that sets up the application with all URLs.</p>
<section id="converting-to-centralized-url-map">
<h2>Converting to Centralized URL Map<a class="headerlink" href="#converting-to-centralized-url-map" title="Link to this heading"></a></h2>
<p>Imagine the current application looks somewhat like this:</p>
<section id="large-applications-as-packages">
<h1>Large Applications as Packages<a class="headerlink" href="#large-applications-as-packages" title="Link to this heading"></a></h1>
<p>Imagine a simple flask application structure that looks like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">/</span><span class="n">yourapplication</span>
<span class="n">yourapplication</span><span class="o">.</span><span class="n">py</span>
<span class="o">/</span><span class="n">static</span>
<span class="n">style</span><span class="o">.</span><span class="n">css</span>
<span class="o">/</span><span class="n">templates</span>
<span class="n">layout</span><span class="o">.</span><span class="n">html</span>
<span class="n">index</span><span class="o">.</span><span class="n">html</span>
<span class="n">login</span><span class="o">.</span><span class="n">html</span>
<span class="o">...</span>
</pre></div>
</div>
<p>While this is fine for small applications, for larger applications
its a good idea to use a package instead of a module.
The <a class="reference internal" href="../tutorial/index.html"><span class="doc">Tutorial</span></a> is structured to use the package pattern,
see the <a class="reference external" href="https://github.com/pallets/flask/tree/main/examples/tutorial">example code</a>.</p>
<section id="simple-packages">
<h2>Simple Packages<a class="headerlink" href="#simple-packages" title="Link to this heading"></a></h2>
<p>To convert that into a larger one, just create a new folder
<code class="file docutils literal notranslate"><span class="pre">yourapplication</span></code> inside the existing one and move everything below it.
Then rename <code class="file docutils literal notranslate"><span class="pre">yourapplication.py</span></code> to <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code>. (Make sure to delete
all <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> files first, otherwise things would most likely break)</p>
<p>You should then end up with something like that:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">/</span><span class="n">yourapplication</span>
<span class="o">/</span><span class="n">yourapplication</span>
<span class="fm">__init__</span><span class="o">.</span><span class="n">py</span>
<span class="o">/</span><span class="n">static</span>
<span class="n">style</span><span class="o">.</span><span class="n">css</span>
<span class="o">/</span><span class="n">templates</span>
<span class="n">layout</span><span class="o">.</span><span class="n">html</span>
<span class="n">index</span><span class="o">.</span><span class="n">html</span>
<span class="n">login</span><span class="o">.</span><span class="n">html</span>
<span class="o">...</span>
</pre></div>
</div>
<p>But how do you run your application now? The naive <code class="docutils literal notranslate"><span class="pre">python</span>
<span class="pre">yourapplication/__init__.py</span></code> will not work. Lets just say that Python
does not want modules in packages to be the startup file. But that is not
a big problem, just add a new file called <code class="file docutils literal notranslate"><span class="pre">pyproject.toml</span></code> next to the inner
<code class="file docutils literal notranslate"><span class="pre">yourapplication</span></code> folder with the following contents:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[project]</span>
<span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;yourapplication&quot;</span>
<span class="n">dependencies</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">&quot;flask&quot;</span><span class="p">,</span>
<span class="p">]</span>
<span class="k">[build-system]</span>
<span class="n">requires</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;flit_core&lt;4&quot;</span><span class="p">]</span>
<span class="n">build-backend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;flit_core.buildapi&quot;</span>
</pre></div>
</div>
<p>Install your application so it is importable:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ pip install -e .
</pre></div>
</div>
<p>To use the <code class="docutils literal notranslate"><span class="pre">flask</span></code> command and run your application you need to set
the <code class="docutils literal notranslate"><span class="pre">--app</span></code> option that tells Flask where to find the application
instance:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ flask --app yourapplication run
</pre></div>
</div>
<p>What did we gain from this? Now we can restructure the application a bit
into multiple modules. The only thing you have to remember is the
following quick checklist:</p>
<ol class="arabic simple">
<li><p>the <code class="code docutils literal notranslate"><span class="pre">Flask</span></code> application object creation has to be in the
<code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> file. That way each module can import it safely and the
<code class="code docutils literal notranslate"><span class="pre">__name__</span></code> variable will resolve to the correct package.</p></li>
<li><p>all the view functions (the ones with a <a class="reference internal" href="../api.html#flask.Flask.route" title="flask.Flask.route"><code class="xref py py-meth docutils literal notranslate"><span class="pre">route()</span></code></a>
decorator on top) have to be imported in the <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> file.
Not the object itself, but the module it is in. Import the view module
<strong>after the application object is created</strong>.</p></li>
</ol>
<p>Heres an example <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code>:</p>
<div class="highlight-default 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="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="kn">import</span><span class="w"> </span><span class="nn">yourapplication.views</span>
</pre></div>
</div>
<p>And this is what <code class="file docutils literal notranslate"><span class="pre">views.py</span></code> would look like:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication</span><span class="w"> </span><span class="kn">import</span> <span class="n">app</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">index</span><span class="p">():</span>
<span class="k">pass</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/user/&lt;username&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user</span><span class="p">(</span><span class="n">username</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">return</span> <span class="s1">&#39;Hello World!&#39;</span>
</pre></div>
</div>
<p>Then, with the centralized approach you would have one file with the views
(<code class="file docutils literal notranslate"><span class="pre">views.py</span></code>) but without any decorator:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">():</span>
<span class="k">pass</span>
<span class="k">def</span><span class="w"> </span><span class="nf">user</span><span class="p">(</span><span class="n">username</span><span class="p">):</span>
<span class="k">pass</span>
<p>You should then end up with something like that:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">/</span><span class="n">yourapplication</span>
<span class="n">pyproject</span><span class="o">.</span><span class="n">toml</span>
<span class="o">/</span><span class="n">yourapplication</span>
<span class="fm">__init__</span><span class="o">.</span><span class="n">py</span>
<span class="n">views</span><span class="o">.</span><span class="n">py</span>
<span class="o">/</span><span class="n">static</span>
<span class="n">style</span><span class="o">.</span><span class="n">css</span>
<span class="o">/</span><span class="n">templates</span>
<span class="n">layout</span><span class="o">.</span><span class="n">html</span>
<span class="n">index</span><span class="o">.</span><span class="n">html</span>
<span class="n">login</span><span class="o">.</span><span class="n">html</span>
<span class="o">...</span>
</pre></div>
</div>
<p>And then a file that sets up an application which maps the functions to
URLs:</p>
<div class="highlight-default 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="kn">from</span><span class="w"> </span><span class="nn">yourapplication</span><span class="w"> </span><span class="kn">import</span> <span class="n">views</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="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="n">view_func</span><span class="o">=</span><span class="n">views</span><span class="o">.</span><span class="n">index</span><span class="p">)</span>
<span class="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span><span class="s1">&#39;/user/&lt;username&gt;&#39;</span><span class="p">,</span> <span class="n">view_func</span><span class="o">=</span><span class="n">views</span><span class="o">.</span><span class="n">user</span><span class="p">)</span>
</pre></div>
<div class="admonition-circular-imports admonition">
<p class="admonition-title">Circular Imports</p>
<p>Every Python programmer hates them, and yet we just added some:
circular imports (Thats when two modules depend on each other. In this
case <code class="file docutils literal notranslate"><span class="pre">views.py</span></code> depends on <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code>). Be advised that this is a
bad idea in general but here it is actually fine. The reason for this is
that we are not actually using the views in <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> and just
ensuring the module is imported and we are doing that at the bottom of
the file.</p>
</div>
</section>
<section id="loading-late">
<h2>Loading Late<a class="headerlink" href="#loading-late" title="Link to this heading"></a></h2>
<p>So far we only split up the views and the routing, but the module is still
loaded upfront. The trick is to actually load the view function as needed.
This can be accomplished with a helper class that behaves just like a
function but internally imports the real function on first use:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">werkzeug.utils</span><span class="w"> </span><span class="kn">import</span> <span class="n">import_string</span><span class="p">,</span> <span class="n">cached_property</span>
<span class="k">class</span><span class="w"> </span><span class="nc">LazyView</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">import_name</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="vm">__module__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__name__</span> <span class="o">=</span> <span class="n">import_name</span><span class="o">.</span><span class="n">rsplit</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">import_name</span> <span class="o">=</span> <span class="n">import_name</span>
<span class="nd">@cached_property</span>
<span class="k">def</span><span class="w"> </span><span class="nf">view</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="n">import_string</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">import_name</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">view</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</pre></div>
</div>
<p>Whats important here is is that <code class="code docutils literal notranslate"><span class="pre">__module__</span></code> and <code class="code docutils literal notranslate"><span class="pre">__name__</span></code> are properly
set. This is used by Flask internally to figure out how to name the
URL rules in case you dont provide a name for the rule yourself.</p>
<p>Then you can define your central place to combine the views like this:</p>
<div class="highlight-default 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="kn">from</span><span class="w"> </span><span class="nn">yourapplication.helpers</span><span class="w"> </span><span class="kn">import</span> <span class="n">LazyView</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="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span>
<span class="n">view_func</span><span class="o">=</span><span class="n">LazyView</span><span class="p">(</span><span class="s1">&#39;yourapplication.views.index&#39;</span><span class="p">))</span>
<span class="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span><span class="s1">&#39;/user/&lt;username&gt;&#39;</span><span class="p">,</span>
<span class="n">view_func</span><span class="o">=</span><span class="n">LazyView</span><span class="p">(</span><span class="s1">&#39;yourapplication.views.user&#39;</span><span class="p">))</span>
</pre></div>
</div>
<p>You can further optimize this in terms of amount of keystrokes needed to
write this by having a function that calls into
<a class="reference internal" href="../api.html#flask.Flask.add_url_rule" title="flask.Flask.add_url_rule"><code class="xref py py-meth docutils literal notranslate"><span class="pre">add_url_rule()</span></code></a> by prefixing a string with the project
name and a dot, and by wrapping <code class="code docutils literal notranslate"><span class="pre">view_func</span></code> in a <code class="code docutils literal notranslate"><span class="pre">LazyView</span></code> as needed.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">url</span><span class="p">(</span><span class="n">import_name</span><span class="p">,</span> <span class="n">url_rules</span><span class="o">=</span><span class="p">[],</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
<span class="n">view</span> <span class="o">=</span> <span class="n">LazyView</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;yourapplication.</span><span class="si">{</span><span class="n">import_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">url_rule</span> <span class="ow">in</span> <span class="n">url_rules</span><span class="p">:</span>
<span class="n">app</span><span class="o">.</span><span class="n">add_url_rule</span><span class="p">(</span><span class="n">url_rule</span><span class="p">,</span> <span class="n">view_func</span><span class="o">=</span><span class="n">view</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
<span class="c1"># add a single route to the index view</span>
<span class="n">url</span><span class="p">(</span><span class="s1">&#39;views.index&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;/&#39;</span><span class="p">])</span>
<span class="c1"># add two routes to a single function endpoint</span>
<span class="n">url_rules</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;/user/&#39;</span><span class="p">,</span><span class="s1">&#39;/user/&lt;username&gt;&#39;</span><span class="p">]</span>
<span class="n">url</span><span class="p">(</span><span class="s1">&#39;views.user&#39;</span><span class="p">,</span> <span class="n">url_rules</span><span class="p">)</span>
</pre></div>
</div>
<p>One thing to keep in mind is that before and after request handlers have
to be in a file that is imported upfront to work properly on the first
request. The same goes for any kind of remaining decorator.</p>
<section id="working-with-blueprints">
<h2>Working with Blueprints<a class="headerlink" href="#working-with-blueprints" title="Link to this heading"></a></h2>
<p>If you have larger applications its recommended to divide them into
smaller groups where each group is implemented with the help of a
blueprint. For a gentle introduction into this topic refer to the
<a class="reference internal" href="../blueprints.html"><span class="doc">Modular Applications with Blueprints</span></a> chapter of the documentation.</p>
</section>
</section>
@ -158,18 +177,18 @@ request. The same goes for any kind of remaining decorator.</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"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Lazily Loading Views</a><ul>
<li><a class="reference internal" href="#converting-to-centralized-url-map">Converting to Centralized URL Map</a></li>
<li><a class="reference internal" href="#loading-late">Loading Late</a></li>
<li><a class="reference internal" href="#">Large Applications as Packages</a><ul>
<li><a class="reference internal" href="#simple-packages">Simple Packages</a></li>
<li><a class="reference internal" href="#working-with-blueprints">Working with Blueprints</a></li>
</ul>
</li>
</ul>
@ -179,8 +198,8 @@ request. The same goes for any kind of remaining decorator.</p>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="javascript.html" title="previous chapter">JavaScript, <code class="docutils literal notranslate"><span class="pre">fetch</span></code>, and JSON</a>
<li>Next: <a href="mongoengine.html" title="next chapter">MongoDB with MongoEngine</a></ul>
<li>Previous: <a href="index.html" title="previous chapter">Patterns for Flask</a>
<li>Next: <a href="appfactories.html" title="next chapter">Application Factories</a></ul>
</li>
</ul>
</li>
@ -204,4 +223,4 @@ request. The same goes for any kind of remaining decorator.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Adding HTTP Method Overrides &#8212; Flask Documentation (3.2.x)</title>
<title>Request Content Checksums &#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="Request Content Checksums" href="requestchecksum.html" />
<link rel="prev" title="Deferred Request Callbacks" href="deferredcallbacks.html" />
<link rel="next" title="Background Tasks with Celery" href="celery.html" />
<link rel="prev" title="Adding HTTP Method Overrides" href="methodoverrides.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,60 +28,72 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="requestchecksum.html" title="Request Content Checksums"
<a href="celery.html" title="Background Tasks with Celery"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="deferredcallbacks.html" title="Deferred Request Callbacks"
<a href="methodoverrides.html" title="Adding HTTP Method Overrides"
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="">Adding HTTP Method Overrides</a></li>
<li class="nav-item nav-item-this"><a href="">Request Content Checksums</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="adding-http-method-overrides">
<h1>Adding HTTP Method Overrides<a class="headerlink" href="#adding-http-method-overrides" title="Link to this heading"></a></h1>
<p>Some HTTP proxies do not support arbitrary HTTP methods or newer HTTP
methods (such as PATCH). In that case its possible to “proxy” HTTP
methods through another HTTP method in total violation of the protocol.</p>
<p>The way this works is by letting the client do an HTTP POST request and
set the <code class="docutils literal notranslate"><span class="pre">X-HTTP-Method-Override</span></code> header. Then the method is replaced
with the header value before being passed to Flask.</p>
<p>This can be accomplished with an HTTP middleware:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">HTTPMethodOverrideMiddleware</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="n">allowed_methods</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">([</span>
<span class="s1">&#39;GET&#39;</span><span class="p">,</span>
<span class="s1">&#39;HEAD&#39;</span><span class="p">,</span>
<span class="s1">&#39;POST&#39;</span><span class="p">,</span>
<span class="s1">&#39;DELETE&#39;</span><span class="p">,</span>
<span class="s1">&#39;PUT&#39;</span><span class="p">,</span>
<span class="s1">&#39;PATCH&#39;</span><span class="p">,</span>
<span class="s1">&#39;OPTIONS&#39;</span>
<span class="p">])</span>
<span class="n">bodyless_methods</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">([</span><span class="s1">&#39;GET&#39;</span><span class="p">,</span> <span class="s1">&#39;HEAD&#39;</span><span class="p">,</span> <span class="s1">&#39;OPTIONS&#39;</span><span class="p">,</span> <span class="s1">&#39;DELETE&#39;</span><span class="p">])</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">app</span>
<section id="request-content-checksums">
<h1>Request Content Checksums<a class="headerlink" href="#request-content-checksums" title="Link to this heading"></a></h1>
<p>Various pieces of code can consume the request data and preprocess it.
For instance JSON data ends up on the request object already read and
processed, form data ends up there as well but goes through a different
code path. This seems inconvenient when you want to calculate the
checksum of the incoming request data. This is necessary sometimes for
some APIs.</p>
<p>Fortunately this is however very simple to change by wrapping the input
stream.</p>
<p>The following example calculates the SHA1 checksum of the incoming data as
it gets read and stores it in the WSGI environment:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">hashlib</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;HTTP_X_HTTP_METHOD_OVERRIDE&#39;</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
<span class="k">if</span> <span class="n">method</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">allowed_methods</span><span class="p">:</span>
<span class="n">environ</span><span class="p">[</span><span class="s1">&#39;REQUEST_METHOD&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">method</span>
<span class="k">if</span> <span class="n">method</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">bodyless_methods</span><span class="p">:</span>
<span class="n">environ</span><span class="p">[</span><span class="s1">&#39;CONTENT_LENGTH&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;0&#39;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
<span class="k">class</span><span class="w"> </span><span class="nc">ChecksumCalcStream</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">stream</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_stream</span> <span class="o">=</span> <span class="n">stream</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_hash</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha1</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="nf">read</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">):</span>
<span class="n">rv</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stream</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="nb">bytes</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_hash</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">rv</span><span class="p">)</span>
<span class="k">return</span> <span class="n">rv</span>
<span class="k">def</span><span class="w"> </span><span class="nf">readline</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size_hint</span><span class="p">):</span>
<span class="n">rv</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stream</span><span class="o">.</span><span class="n">readline</span><span class="p">(</span><span class="n">size_hint</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_hash</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">rv</span><span class="p">)</span>
<span class="k">return</span> <span class="n">rv</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate_checksum</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
<span class="n">env</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span>
<span class="n">stream</span> <span class="o">=</span> <span class="n">ChecksumCalcStream</span><span class="p">(</span><span class="n">env</span><span class="p">[</span><span class="s1">&#39;wsgi.input&#39;</span><span class="p">])</span>
<span class="n">env</span><span class="p">[</span><span class="s1">&#39;wsgi.input&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">stream</span>
<span class="k">return</span> <span class="n">stream</span><span class="o">.</span><span class="n">_hash</span>
</pre></div>
</div>
<p>To use this with Flask, wrap the app object with the middleware:</p>
<div class="highlight-default 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="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="n">app</span><span class="o">.</span><span class="n">wsgi_app</span> <span class="o">=</span> <span class="n">HTTPMethodOverrideMiddleware</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">wsgi_app</span><span class="p">)</span>
<p>To use this, all you need to do is to hook the calculating stream in
before the request starts consuming data. (Eg: be careful accessing
<code class="docutils literal notranslate"><span class="pre">request.form</span></code> or anything of that nature. <code class="docutils literal notranslate"><span class="pre">before_request_handlers</span></code>
for instance should be careful not to access it).</p>
<p>Example usage:</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;/special-api&#39;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</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">special_api</span><span class="p">():</span>
<span class="nb">hash</span> <span class="o">=</span> <span class="n">generate_checksum</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>
<span class="c1"># Accessing this parses the input stream</span>
<span class="n">files</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">files</span>
<span class="c1"># At this point the hash is fully constructed.</span>
<span class="n">checksum</span> <span class="o">=</span> <span class="nb">hash</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
<span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;Hash was: </span><span class="si">{</span><span class="n">checksum</span><span class="si">}</span><span class="s2">&quot;</span>
</pre></div>
</div>
</section>
@ -94,20 +106,20 @@ with the header value before being passed to Flask.</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"/>
</a></p>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="deferredcallbacks.html" title="previous chapter">Deferred Request Callbacks</a>
<li>Next: <a href="requestchecksum.html" title="next chapter">Request Content Checksums</a></ul>
<li>Previous: <a href="methodoverrides.html" title="previous chapter">Adding HTTP Method Overrides</a>
<li>Next: <a href="celery.html" title="next chapter">Background Tasks with Celery</a></ul>
</li>
</ul>
</li>
@ -131,4 +143,4 @@ with the header value before being passed to Flask.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>MongoDB with MongoEngine &#8212; Flask Documentation (3.2.x)</title>
<title>Single-Page Applications &#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="Adding a favicon" href="favicon.html" />
<link rel="prev" title="Lazily Loading Views" href="lazyloading.html" />
<link rel="next" title="Security Considerations" href="../web-security.html" />
<link rel="prev" title="Subclassing Flask" href="subclassing.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,113 +28,45 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="favicon.html" title="Adding a favicon"
<a href="../web-security.html" title="Security Considerations"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="lazyloading.html" title="Lazily Loading Views"
<a href="subclassing.html" title="Subclassing Flask"
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="">MongoDB with MongoEngine</a></li>
<li class="nav-item nav-item-this"><a href="">Single-Page Applications</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="mongodb-with-mongoengine">
<h1>MongoDB with MongoEngine<a class="headerlink" href="#mongodb-with-mongoengine" title="Link to this heading"></a></h1>
<p>Using a document database like MongoDB is a common alternative to
relational SQL databases. This pattern shows how to use
<a class="reference external" href="http://mongoengine.org">MongoEngine</a>, a document mapper library, to integrate with MongoDB.</p>
<p>A running MongoDB server and <a class="reference external" href="https://flask-mongoengine.readthedocs.io">Flask-MongoEngine</a> are required.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pip</span> <span class="n">install</span> <span class="n">flask</span><span class="o">-</span><span class="n">mongoengine</span>
</pre></div>
</div>
<section id="configuration">
<h2>Configuration<a class="headerlink" href="#configuration" title="Link to this heading"></a></h2>
<p>Basic setup can be done by defining <code class="docutils literal notranslate"><span class="pre">MONGODB_SETTINGS</span></code> on
<code class="docutils literal notranslate"><span class="pre">app.config</span></code> and creating a <code class="docutils literal notranslate"><span class="pre">MongoEngine</span></code> instance.</p>
<div class="highlight-default 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="kn">from</span><span class="w"> </span><span class="nn">flask_mongoengine</span><span class="w"> </span><span class="kn">import</span> <span class="n">MongoEngine</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="n">app</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;MONGODB_SETTINGS&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">&quot;db&quot;</span><span class="p">:</span> <span class="s2">&quot;myapp&quot;</span><span class="p">,</span>
<span class="p">}</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">MongoEngine</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="mapping-documents">
<h2>Mapping Documents<a class="headerlink" href="#mapping-documents" title="Link to this heading"></a></h2>
<p>To declare a model that represents a Mongo document, create a class that
inherits from <code class="docutils literal notranslate"><span class="pre">Document</span></code> and declare each of the fields.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">mongoengine</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">me</span>
<section id="single-page-applications">
<h1>Single-Page Applications<a class="headerlink" href="#single-page-applications" title="Link to this heading"></a></h1>
<p>Flask can be used to serve Single-Page Applications (SPA) by placing static
files produced by your frontend framework in a subfolder inside of your
project. You will also need to create a catch-all endpoint that routes all
requests to your SPA.</p>
<p>The following example demonstrates how to serve an SPA along with an API:</p>
<div class="highlight-default 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">jsonify</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Movie</span><span class="p">(</span><span class="n">me</span><span class="o">.</span><span class="n">Document</span><span class="p">):</span>
<span class="n">title</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">StringField</span><span class="p">(</span><span class="n">required</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">year</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">IntField</span><span class="p">()</span>
<span class="n">rated</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">StringField</span><span class="p">()</span>
<span class="n">director</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">StringField</span><span class="p">()</span>
<span class="n">actors</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">ListField</span><span class="p">()</span>
</pre></div>
</div>
<p>If the document has nested fields, use <code class="docutils literal notranslate"><span class="pre">EmbeddedDocument</span></code> to
defined the fields of the embedded document and
<code class="docutils literal notranslate"><span class="pre">EmbeddedDocumentField</span></code> to declare it on the parent document.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Imdb</span><span class="p">(</span><span class="n">me</span><span class="o">.</span><span class="n">EmbeddedDocument</span><span class="p">):</span>
<span class="n">imdb_id</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">StringField</span><span class="p">()</span>
<span class="n">rating</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">DecimalField</span><span class="p">()</span>
<span class="n">votes</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">IntField</span><span class="p">()</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="n">static_folder</span><span class="o">=</span><span class="s1">&#39;app&#39;</span><span class="p">,</span> <span class="n">static_url_path</span><span class="o">=</span><span class="s2">&quot;/app&quot;</span><span class="p">)</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Movie</span><span class="p">(</span><span class="n">me</span><span class="o">.</span><span class="n">Document</span><span class="p">):</span>
<span class="o">...</span>
<span class="n">imdb</span> <span class="o">=</span> <span class="n">me</span><span class="o">.</span><span class="n">EmbeddedDocumentField</span><span class="p">(</span><span class="n">Imdb</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="creating-data">
<h2>Creating Data<a class="headerlink" href="#creating-data" title="Link to this heading"></a></h2>
<p>Instantiate your document class with keyword arguments for the fields.
You can also assign values to the field attributes after instantiation.
Then call <code class="docutils literal notranslate"><span class="pre">doc.save()</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">bttf</span> <span class="o">=</span> <span class="n">Movie</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="s2">&quot;Back To The Future&quot;</span><span class="p">,</span> <span class="n">year</span><span class="o">=</span><span class="mi">1985</span><span class="p">)</span>
<span class="n">bttf</span><span class="o">.</span><span class="n">actors</span> <span class="o">=</span> <span class="p">[</span>
<span class="s2">&quot;Michael J. Fox&quot;</span><span class="p">,</span>
<span class="s2">&quot;Christopher Lloyd&quot;</span>
<span class="p">]</span>
<span class="n">bttf</span><span class="o">.</span><span class="n">imdb</span> <span class="o">=</span> <span class="n">Imdb</span><span class="p">(</span><span class="n">imdb_id</span><span class="o">=</span><span class="s2">&quot;tt0088763&quot;</span><span class="p">,</span> <span class="n">rating</span><span class="o">=</span><span class="mf">8.5</span><span class="p">)</span>
<span class="n">bttf</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
</pre></div>
</div>
</section>
<section id="queries">
<h2>Queries<a class="headerlink" href="#queries" title="Link to this heading"></a></h2>
<p>Use the class <code class="docutils literal notranslate"><span class="pre">objects</span></code> attribute to make queries. A keyword argument
looks for an equal value on the field.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">bttf</span> <span class="o">=</span> <span class="n">Movie</span><span class="o">.</span><span class="n">objects</span><span class="p">(</span><span class="n">title</span><span class="o">=</span><span class="s2">&quot;Back To The Future&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">get_or_404</span><span class="p">()</span>
</pre></div>
</div>
<p>Query operators may be used by concatenating them with the field name
using a double-underscore. <code class="docutils literal notranslate"><span class="pre">objects</span></code>, and queries returned by
calling it, are iterable.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">some_theron_movie</span> <span class="o">=</span> <span class="n">Movie</span><span class="o">.</span><span class="n">objects</span><span class="p">(</span><span class="n">actors__in</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;Charlize Theron&quot;</span><span class="p">])</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="k">for</span> <span class="n">recents</span> <span class="ow">in</span> <span class="n">Movie</span><span class="o">.</span><span class="n">objects</span><span class="p">(</span><span class="n">year__gte</span><span class="o">=</span><span class="mi">2017</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="n">recents</span><span class="o">.</span><span class="n">title</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="s2">&quot;/heartbeat&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">heartbeat</span><span class="p">():</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">({</span><span class="s2">&quot;status&quot;</span><span class="p">:</span> <span class="s2">&quot;healthy&quot;</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="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;path&#39;</span><span class="p">:</span> <span class="s1">&#39;&#39;</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;/&lt;path:path&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">catch_all</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
<span class="k">return</span> <span class="n">app</span><span class="o">.</span><span class="n">send_static_file</span><span class="p">(</span><span class="s2">&quot;index.html&quot;</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="documentation">
<h2>Documentation<a class="headerlink" href="#documentation" title="Link to this heading"></a></h2>
<p>There are many more ways to define and query documents with MongoEngine.
For more information, check out the <a class="reference external" href="http://mongoengine.org">official documentation</a>.</p>
<p>Flask-MongoEngine adds helpful utilities on top of MongoEngine. Check
out their <a class="reference external" href="https://flask-mongoengine.readthedocs.io">documentation</a> as well.</p>
</section>
</section>
@ -145,32 +77,20 @@ out their <a class="reference external" href="https://flask-mongoengine.readthed
<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="#">MongoDB with MongoEngine</a><ul>
<li><a class="reference internal" href="#configuration">Configuration</a></li>
<li><a class="reference internal" href="#mapping-documents">Mapping Documents</a></li>
<li><a class="reference internal" href="#creating-data">Creating Data</a></li>
<li><a class="reference internal" href="#queries">Queries</a></li>
<li><a class="reference internal" href="#documentation">Documentation</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="lazyloading.html" title="previous chapter">Lazily Loading Views</a>
<li>Next: <a href="favicon.html" title="next chapter">Adding a favicon</a></ul>
<li>Previous: <a href="subclassing.html" title="previous chapter">Subclassing Flask</a>
<li>Next: <a href="../web-security.html" title="next chapter">Security Considerations</a></ul>
</li>
</ul>
</li>
@ -194,4 +114,4 @@ out their <a class="reference external" href="https://flask-mongoengine.readthed
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Large Applications as Packages &#8212; Flask Documentation (3.2.x)</title>
<title>SQLAlchemy in Flask &#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="Application Factories" href="appfactories.html" />
<link rel="prev" title="Patterns for Flask" href="index.html" />
<link rel="next" title="Uploading Files" href="fileuploads.html" />
<link rel="prev" title="Using SQLite 3 with Flask" href="sqlite3.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,144 +28,217 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="appfactories.html" title="Application Factories"
<a href="fileuploads.html" title="Uploading Files"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="index.html" title="Patterns for Flask"
<a href="sqlite3.html" title="Using SQLite 3 with Flask"
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="">Large Applications as Packages</a></li>
<li class="nav-item nav-item-this"><a href="">SQLAlchemy in Flask</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="large-applications-as-packages">
<h1>Large Applications as Packages<a class="headerlink" href="#large-applications-as-packages" title="Link to this heading"></a></h1>
<p>Imagine a simple flask application structure that looks like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">/</span><span class="n">yourapplication</span>
<span class="n">yourapplication</span><span class="o">.</span><span class="n">py</span>
<span class="o">/</span><span class="n">static</span>
<span class="n">style</span><span class="o">.</span><span class="n">css</span>
<span class="o">/</span><span class="n">templates</span>
<span class="n">layout</span><span class="o">.</span><span class="n">html</span>
<span class="n">index</span><span class="o">.</span><span class="n">html</span>
<span class="n">login</span><span class="o">.</span><span class="n">html</span>
<span class="o">...</span>
</pre></div>
</div>
<p>While this is fine for small applications, for larger applications
its a good idea to use a package instead of a module.
The <a class="reference internal" href="../tutorial/index.html"><span class="doc">Tutorial</span></a> is structured to use the package pattern,
see the <a class="reference external" href="https://github.com/pallets/flask/tree/main/examples/tutorial">example code</a>.</p>
<section id="simple-packages">
<h2>Simple Packages<a class="headerlink" href="#simple-packages" title="Link to this heading"></a></h2>
<p>To convert that into a larger one, just create a new folder
<code class="file docutils literal notranslate"><span class="pre">yourapplication</span></code> inside the existing one and move everything below it.
Then rename <code class="file docutils literal notranslate"><span class="pre">yourapplication.py</span></code> to <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code>. (Make sure to delete
all <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> files first, otherwise things would most likely break)</p>
<p>You should then end up with something like that:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">/</span><span class="n">yourapplication</span>
<span class="o">/</span><span class="n">yourapplication</span>
<span class="fm">__init__</span><span class="o">.</span><span class="n">py</span>
<span class="o">/</span><span class="n">static</span>
<span class="n">style</span><span class="o">.</span><span class="n">css</span>
<span class="o">/</span><span class="n">templates</span>
<span class="n">layout</span><span class="o">.</span><span class="n">html</span>
<span class="n">index</span><span class="o">.</span><span class="n">html</span>
<span class="n">login</span><span class="o">.</span><span class="n">html</span>
<span class="o">...</span>
</pre></div>
</div>
<p>But how do you run your application now? The naive <code class="docutils literal notranslate"><span class="pre">python</span>
<span class="pre">yourapplication/__init__.py</span></code> will not work. Lets just say that Python
does not want modules in packages to be the startup file. But that is not
a big problem, just add a new file called <code class="file docutils literal notranslate"><span class="pre">pyproject.toml</span></code> next to the inner
<code class="file docutils literal notranslate"><span class="pre">yourapplication</span></code> folder with the following contents:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[project]</span>
<span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;yourapplication&quot;</span>
<span class="n">dependencies</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">&quot;flask&quot;</span><span class="p">,</span>
<span class="p">]</span>
<span class="k">[build-system]</span>
<span class="n">requires</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;flit_core&lt;4&quot;</span><span class="p">]</span>
<span class="n">build-backend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;flit_core.buildapi&quot;</span>
</pre></div>
</div>
<p>Install your application so it is importable:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ pip install -e .
</pre></div>
</div>
<p>To use the <code class="docutils literal notranslate"><span class="pre">flask</span></code> command and run your application you need to set
the <code class="docutils literal notranslate"><span class="pre">--app</span></code> option that tells Flask where to find the application
instance:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ flask --app yourapplication run
</pre></div>
</div>
<p>What did we gain from this? Now we can restructure the application a bit
into multiple modules. The only thing you have to remember is the
following quick checklist:</p>
<ol class="arabic simple">
<li><p>the <code class="code docutils literal notranslate"><span class="pre">Flask</span></code> application object creation has to be in the
<code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> file. That way each module can import it safely and the
<code class="code docutils literal notranslate"><span class="pre">__name__</span></code> variable will resolve to the correct package.</p></li>
<li><p>all the view functions (the ones with a <a class="reference internal" href="../api.html#flask.Flask.route" title="flask.Flask.route"><code class="xref py py-meth docutils literal notranslate"><span class="pre">route()</span></code></a>
decorator on top) have to be imported in the <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> file.
Not the object itself, but the module it is in. Import the view module
<strong>after the application object is created</strong>.</p></li>
</ol>
<p>Heres an example <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code>:</p>
<div class="highlight-default 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="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>
<section id="sqlalchemy-in-flask">
<h1>SQLAlchemy in Flask<a class="headerlink" href="#sqlalchemy-in-flask" title="Link to this heading"></a></h1>
<p>Many people prefer <a class="reference external" href="https://www.sqlalchemy.org/">SQLAlchemy</a> for database access. In this case its
encouraged to use a package instead of a module for your flask application
and drop the models into a separate module (<a class="reference internal" href="packages.html"><span class="doc">Large Applications as Packages</span></a>). While that
is not necessary, it makes a lot of sense.</p>
<p>There are four very common ways to use SQLAlchemy. I will outline each
of them here:</p>
<section id="flask-sqlalchemy-extension">
<h2>Flask-SQLAlchemy Extension<a class="headerlink" href="#flask-sqlalchemy-extension" title="Link to this heading"></a></h2>
<p>Because SQLAlchemy is a common database abstraction layer and object
relational mapper that requires a little bit of configuration effort,
there is a Flask extension that handles that for you. This is recommended
if you want to get started quickly.</p>
<p>You can download <a class="reference external" href="https://flask-sqlalchemy.palletsprojects.com/">Flask-SQLAlchemy</a> from <a class="reference external" href="https://pypi.org/project/Flask-SQLAlchemy/">PyPI</a>.</p>
</section>
<section id="declarative">
<h2>Declarative<a class="headerlink" href="#declarative" title="Link to this heading"></a></h2>
<p>The declarative extension in SQLAlchemy is the most recent method of using
SQLAlchemy. It allows you to define tables and models in one go, similar
to how Django works. In addition to the following text I recommend the
official documentation on the <a class="reference external" href="https://docs.sqlalchemy.org/en/latest/orm/extensions/declarative/">declarative</a> extension.</p>
<p>Heres the example <code class="file docutils literal notranslate"><span class="pre">database.py</span></code> module for your application:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_engine</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.orm</span><span class="w"> </span><span class="kn">import</span> <span class="n">scoped_session</span><span class="p">,</span> <span class="n">sessionmaker</span><span class="p">,</span> <span class="n">declarative_base</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">yourapplication.views</span>
</pre></div>
</div>
<p>And this is what <code class="file docutils literal notranslate"><span class="pre">views.py</span></code> would look like:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication</span><span class="w"> </span><span class="kn">import</span> <span class="n">app</span>
<span class="n">engine</span> <span class="o">=</span> <span class="n">create_engine</span><span class="p">(</span><span class="s1">&#39;sqlite:////tmp/test.db&#39;</span><span class="p">)</span>
<span class="n">db_session</span> <span class="o">=</span> <span class="n">scoped_session</span><span class="p">(</span><span class="n">sessionmaker</span><span class="p">(</span><span class="n">autocommit</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">autoflush</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">))</span>
<span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
<span class="n">Base</span><span class="o">.</span><span class="n">query</span> <span class="o">=</span> <span class="n">db_session</span><span class="o">.</span><span class="n">query_property</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">index</span><span class="p">():</span>
<span class="k">return</span> <span class="s1">&#39;Hello World!&#39;</span>
<span class="k">def</span><span class="w"> </span><span class="nf">init_db</span><span class="p">():</span>
<span class="c1"># import all modules here that might define models so that</span>
<span class="c1"># they will be registered properly on the metadata. Otherwise</span>
<span class="c1"># you will have to import them first before calling init_db()</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">yourapplication.models</span>
<span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="o">.</span><span class="n">create_all</span><span class="p">(</span><span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">)</span>
</pre></div>
</div>
<p>You should then end up with something like that:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">/</span><span class="n">yourapplication</span>
<span class="n">pyproject</span><span class="o">.</span><span class="n">toml</span>
<span class="o">/</span><span class="n">yourapplication</span>
<span class="fm">__init__</span><span class="o">.</span><span class="n">py</span>
<span class="n">views</span><span class="o">.</span><span class="n">py</span>
<span class="o">/</span><span class="n">static</span>
<span class="n">style</span><span class="o">.</span><span class="n">css</span>
<span class="o">/</span><span class="n">templates</span>
<span class="n">layout</span><span class="o">.</span><span class="n">html</span>
<span class="n">index</span><span class="o">.</span><span class="n">html</span>
<span class="n">login</span><span class="o">.</span><span class="n">html</span>
<span class="o">...</span>
<p>To define your models, just subclass the <code class="code docutils literal notranslate"><span class="pre">Base</span></code> class that was created by
the code above. If you are wondering why we dont have to care about
threads here (like we did in the SQLite3 example above with the
<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> object): thats because SQLAlchemy does that for us
already with the <a class="reference external" href="https://docs.sqlalchemy.org/en/20/orm/contextual.html#sqlalchemy.orm.scoped_session" title="(in SQLAlchemy v2.0)"><code class="xref py py-class docutils literal notranslate"><span class="pre">scoped_session</span></code></a>.</p>
<p>To use SQLAlchemy in a declarative way with your application, you just
have to put the following code into your application module. Flask will
automatically remove database sessions at the end of the request or
when the application shuts down:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">db_session</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">teardown_appcontext</span>
<span class="k">def</span><span class="w"> </span><span class="nf">shutdown_session</span><span class="p">(</span><span class="n">exception</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="n">db_session</span><span class="o">.</span><span class="n">remove</span><span class="p">()</span>
</pre></div>
</div>
<div class="admonition-circular-imports admonition">
<p class="admonition-title">Circular Imports</p>
<p>Every Python programmer hates them, and yet we just added some:
circular imports (Thats when two modules depend on each other. In this
case <code class="file docutils literal notranslate"><span class="pre">views.py</span></code> depends on <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code>). Be advised that this is a
bad idea in general but here it is actually fine. The reason for this is
that we are not actually using the views in <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> and just
ensuring the module is imported and we are doing that at the bottom of
the file.</p>
<p>Here is an example model (put this into <code class="file docutils literal notranslate"><span class="pre">models.py</span></code>, e.g.):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">Column</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">String</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">Base</span>
<span class="k">class</span><span class="w"> </span><span class="nc">User</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s1">&#39;users&#39;</span>
<span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">name</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">email</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="mi">120</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="n">email</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="sa">f</span><span class="s1">&#39;&lt;User </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">!r}</span><span class="s1">&gt;&#39;</span>
</pre></div>
</div>
<p>To create the database you can use the <code class="code docutils literal notranslate"><span class="pre">init_db</span></code> function:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">init_db</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">init_db</span><span class="p">()</span>
</pre></div>
</div>
<p>You can insert entries into the database like this:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">db_session</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.models</span><span class="w"> </span><span class="kn">import</span> <span class="n">User</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">u</span> <span class="o">=</span> <span class="n">User</span><span class="p">(</span><span class="s1">&#39;admin&#39;</span><span class="p">,</span> <span class="s1">&#39;admin@localhost&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db_session</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db_session</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</pre></div>
</div>
<p>Querying is simple as well:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="go">[&lt;User &#39;admin&#39;&gt;]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s1">&#39;admin&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="go">&lt;User &#39;admin&#39;&gt;</span>
</pre></div>
</div>
</section>
<section id="working-with-blueprints">
<h2>Working with Blueprints<a class="headerlink" href="#working-with-blueprints" title="Link to this heading"></a></h2>
<p>If you have larger applications its recommended to divide them into
smaller groups where each group is implemented with the help of a
blueprint. For a gentle introduction into this topic refer to the
<a class="reference internal" href="../blueprints.html"><span class="doc">Modular Applications with Blueprints</span></a> chapter of the documentation.</p>
<section id="manual-object-relational-mapping">
<h2>Manual Object Relational Mapping<a class="headerlink" href="#manual-object-relational-mapping" title="Link to this heading"></a></h2>
<p>Manual object relational mapping has a few upsides and a few downsides
versus the declarative approach from above. The main difference is that
you define tables and classes separately and map them together. Its more
flexible but a little more to type. In general it works like the
declarative approach, so make sure to also split up your application into
multiple modules in a package.</p>
<p>Here is an example <code class="file docutils literal notranslate"><span class="pre">database.py</span></code> module for your application:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_engine</span><span class="p">,</span> <span class="n">MetaData</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.orm</span><span class="w"> </span><span class="kn">import</span> <span class="n">scoped_session</span><span class="p">,</span> <span class="n">sessionmaker</span>
<span class="n">engine</span> <span class="o">=</span> <span class="n">create_engine</span><span class="p">(</span><span class="s1">&#39;sqlite:////tmp/test.db&#39;</span><span class="p">)</span>
<span class="n">metadata</span> <span class="o">=</span> <span class="n">MetaData</span><span class="p">()</span>
<span class="n">db_session</span> <span class="o">=</span> <span class="n">scoped_session</span><span class="p">(</span><span class="n">sessionmaker</span><span class="p">(</span><span class="n">autocommit</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">autoflush</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">))</span>
<span class="k">def</span><span class="w"> </span><span class="nf">init_db</span><span class="p">():</span>
<span class="n">metadata</span><span class="o">.</span><span class="n">create_all</span><span class="p">(</span><span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">)</span>
</pre></div>
</div>
<p>As in the declarative approach, you need to close the session after
each request or application context shutdown. Put this into your
application module:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">db_session</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">teardown_appcontext</span>
<span class="k">def</span><span class="w"> </span><span class="nf">shutdown_session</span><span class="p">(</span><span class="n">exception</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="n">db_session</span><span class="o">.</span><span class="n">remove</span><span class="p">()</span>
</pre></div>
</div>
<p>Here is an example table and model (put this into <code class="file docutils literal notranslate"><span class="pre">models.py</span></code>):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">Table</span><span class="p">,</span> <span class="n">Column</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">String</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.orm</span><span class="w"> </span><span class="kn">import</span> <span class="n">mapper</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">db_session</span>
<span class="k">class</span><span class="w"> </span><span class="nc">User</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="n">query</span> <span class="o">=</span> <span class="n">db_session</span><span class="o">.</span><span class="n">query_property</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="n">email</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="sa">f</span><span class="s1">&#39;&lt;User </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">!r}</span><span class="s1">&gt;&#39;</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s1">&#39;users&#39;</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">&#39;id&#39;</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="kc">True</span><span class="p">),</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="kc">True</span><span class="p">),</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">&#39;email&#39;</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">120</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="p">)</span>
<span class="n">mapper</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">users</span><span class="p">)</span>
</pre></div>
</div>
<p>Querying and inserting works exactly the same as in the example above.</p>
</section>
<section id="sql-abstraction-layer">
<h2>SQL Abstraction Layer<a class="headerlink" href="#sql-abstraction-layer" title="Link to this heading"></a></h2>
<p>If you just want to use the database system (and SQL) abstraction layer
you basically only need the engine:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_engine</span><span class="p">,</span> <span class="n">MetaData</span><span class="p">,</span> <span class="n">Table</span>
<span class="n">engine</span> <span class="o">=</span> <span class="n">create_engine</span><span class="p">(</span><span class="s1">&#39;sqlite:////tmp/test.db&#39;</span><span class="p">)</span>
<span class="n">metadata</span> <span class="o">=</span> <span class="n">MetaData</span><span class="p">(</span><span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">)</span>
</pre></div>
</div>
<p>Then you can either declare the tables in your code like in the examples
above, or automatically load them:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">Table</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s1">&#39;users&#39;</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">autoload</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div>
</div>
<p>To insert data you can use the <code class="code docutils literal notranslate"><span class="pre">insert</span></code> method. We have to get a
connection first so that we can use a transaction:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">con</span> <span class="o">=</span> <span class="n">engine</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">con</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">insert</span><span class="p">(),</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;admin&#39;</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="s1">&#39;admin@localhost&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>SQLAlchemy will automatically commit for us.</p>
<p>To query your database, you use the engine directly or use a connection:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">users</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">execute</span><span class="p">()</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="go">(1, &#39;admin&#39;, &#39;admin@localhost&#39;)</span>
</pre></div>
</div>
<p>These results are also dict-like tuples:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">execute</span><span class="p">()</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">]</span>
<span class="go">&#39;admin&#39;</span>
</pre></div>
</div>
<p>You can also pass strings of SQL statements to the
<code class="xref py py-meth docutils literal notranslate"><span class="pre">execute()</span></code> method:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">engine</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s1">&#39;select * from users where id = :1&#39;</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">])</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="go">(1, &#39;admin&#39;, &#39;admin@localhost&#39;)</span>
</pre></div>
</div>
<p>For more information about SQLAlchemy, head over to the
<a class="reference external" href="https://www.sqlalchemy.org/">website</a>.</p>
</section>
</section>
@ -177,18 +250,20 @@ blueprint. For a gentle introduction into this topic refer to the
<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="#">Large Applications as Packages</a><ul>
<li><a class="reference internal" href="#simple-packages">Simple Packages</a></li>
<li><a class="reference internal" href="#working-with-blueprints">Working with Blueprints</a></li>
<li><a class="reference internal" href="#">SQLAlchemy in Flask</a><ul>
<li><a class="reference internal" href="#flask-sqlalchemy-extension">Flask-SQLAlchemy Extension</a></li>
<li><a class="reference internal" href="#declarative">Declarative</a></li>
<li><a class="reference internal" href="#manual-object-relational-mapping">Manual Object Relational Mapping</a></li>
<li><a class="reference internal" href="#sql-abstraction-layer">SQL Abstraction Layer</a></li>
</ul>
</li>
</ul>
@ -198,8 +273,8 @@ blueprint. For a gentle introduction into this topic refer to the
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="index.html" title="previous chapter">Patterns for Flask</a>
<li>Next: <a href="appfactories.html" title="next chapter">Application Factories</a></ul>
<li>Previous: <a href="sqlite3.html" title="previous chapter">Using SQLite 3 with Flask</a>
<li>Next: <a href="fileuploads.html" title="next chapter">Uploading Files</a></ul>
</li>
</ul>
</li>
@ -223,4 +298,4 @@ blueprint. For a gentle introduction into this topic refer to the
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Request Content Checksums &#8212; Flask Documentation (3.2.x)</title>
<title>Using SQLite 3 with Flask &#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="Background Tasks with Celery" href="celery.html" />
<link rel="prev" title="Adding HTTP Method Overrides" href="methodoverrides.html" />
<link rel="next" title="SQLAlchemy in Flask" href="sqlalchemy.html" />
<link rel="prev" title="Using URL Processors" href="urlprocessors.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,74 +28,162 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="celery.html" title="Background Tasks with Celery"
<a href="sqlalchemy.html" title="SQLAlchemy in Flask"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="methodoverrides.html" title="Adding HTTP Method Overrides"
<a href="urlprocessors.html" title="Using URL Processors"
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="">Request Content Checksums</a></li>
<li class="nav-item nav-item-this"><a href="">Using SQLite 3 with Flask</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="request-content-checksums">
<h1>Request Content Checksums<a class="headerlink" href="#request-content-checksums" title="Link to this heading"></a></h1>
<p>Various pieces of code can consume the request data and preprocess it.
For instance JSON data ends up on the request object already read and
processed, form data ends up there as well but goes through a different
code path. This seems inconvenient when you want to calculate the
checksum of the incoming request data. This is necessary sometimes for
some APIs.</p>
<p>Fortunately this is however very simple to change by wrapping the input
stream.</p>
<p>The following example calculates the SHA1 checksum of the incoming data as
it gets read and stores it in the WSGI environment:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">hashlib</span>
<span class="k">class</span><span class="w"> </span><span class="nc">ChecksumCalcStream</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<section id="using-sqlite-3-with-flask">
<h1>Using SQLite 3 with Flask<a class="headerlink" href="#using-sqlite-3-with-flask" title="Link to this heading"></a></h1>
<p>In Flask you can easily implement the opening of database connections on
demand and closing them when the context dies (usually at the end of the
request).</p>
<p>Here is a simple example of how you can use SQLite 3 with Flask:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">sqlite3</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">g</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">stream</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_stream</span> <span class="o">=</span> <span class="n">stream</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_hash</span> <span class="o">=</span> <span class="n">hashlib</span><span class="o">.</span><span class="n">sha1</span><span class="p">()</span>
<span class="n">DATABASE</span> <span class="o">=</span> <span class="s1">&#39;/path/to/database.db&#39;</span>
<span class="k">def</span><span class="w"> </span><span class="nf">read</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">):</span>
<span class="n">rv</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stream</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="nb">bytes</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_hash</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">rv</span><span class="p">)</span>
<span class="k">return</span> <span class="n">rv</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_db</span><span class="p">():</span>
<span class="n">db</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="s1">&#39;_database&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="k">if</span> <span class="n">db</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">g</span><span class="o">.</span><span class="n">_database</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">DATABASE</span><span class="p">)</span>
<span class="k">return</span> <span class="n">db</span>
<span class="k">def</span><span class="w"> </span><span class="nf">readline</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">size_hint</span><span class="p">):</span>
<span class="n">rv</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stream</span><span class="o">.</span><span class="n">readline</span><span class="p">(</span><span class="n">size_hint</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_hash</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">rv</span><span class="p">)</span>
<span class="k">return</span> <span class="n">rv</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate_checksum</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
<span class="n">env</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span>
<span class="n">stream</span> <span class="o">=</span> <span class="n">ChecksumCalcStream</span><span class="p">(</span><span class="n">env</span><span class="p">[</span><span class="s1">&#39;wsgi.input&#39;</span><span class="p">])</span>
<span class="n">env</span><span class="p">[</span><span class="s1">&#39;wsgi.input&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">stream</span>
<span class="k">return</span> <span class="n">stream</span><span class="o">.</span><span class="n">_hash</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">teardown_appcontext</span>
<span class="k">def</span><span class="w"> </span><span class="nf">close_connection</span><span class="p">(</span><span class="n">exception</span><span class="p">):</span>
<span class="n">db</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="s1">&#39;_database&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="k">if</span> <span class="n">db</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">db</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p>To use this, all you need to do is to hook the calculating stream in
before the request starts consuming data. (Eg: be careful accessing
<code class="docutils literal notranslate"><span class="pre">request.form</span></code> or anything of that nature. <code class="docutils literal notranslate"><span class="pre">before_request_handlers</span></code>
for instance should be careful not to access it).</p>
<p>Example usage:</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;/special-api&#39;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</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">special_api</span><span class="p">():</span>
<span class="nb">hash</span> <span class="o">=</span> <span class="n">generate_checksum</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>
<span class="c1"># Accessing this parses the input stream</span>
<span class="n">files</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">files</span>
<span class="c1"># At this point the hash is fully constructed.</span>
<span class="n">checksum</span> <span class="o">=</span> <span class="nb">hash</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span>
<span class="k">return</span> <span class="sa">f</span><span class="s2">&quot;Hash was: </span><span class="si">{</span><span class="n">checksum</span><span class="si">}</span><span class="s2">&quot;</span>
<p>Now, to use the database, the application must either have an active
application context (which is always true if there is a request in flight)
or create an application context itself. At that point the <code class="docutils literal notranslate"><span class="pre">get_db</span></code>
function can be used to get the current database connection. Whenever the
context is destroyed the database connection will be terminated.</p>
<p>Example:</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;/&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">():</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">get_db</span><span class="p">()</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
<span class="o">...</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Please keep in mind that the teardown request and appcontext functions
are always executed, even if a before-request handler failed or was
never executed. Because of this we have to make sure here that the
database is there before we close it.</p>
</div>
<section id="connect-on-demand">
<h2>Connect on Demand<a class="headerlink" href="#connect-on-demand" title="Link to this heading"></a></h2>
<p>The upside of this approach (connecting on first use) is that this will
only open the connection if truly necessary. If you want to use this
code outside a request context you can use it in a Python shell by opening
the application context by hand:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">app_context</span><span class="p">():</span>
<span class="c1"># now you can use get_db()</span>
</pre></div>
</div>
</section>
<section id="easy-querying">
<h2>Easy Querying<a class="headerlink" href="#easy-querying" title="Link to this heading"></a></h2>
<p>Now in each request handling function you can access <code class="code docutils literal notranslate"><span class="pre">get_db()</span></code> to get the
current open database connection. To simplify working with SQLite, a
row factory function is useful. It is executed for every result returned
from the database to convert the result. For instance, in order to get
dictionaries instead of tuples, this could be inserted into the <code class="docutils literal notranslate"><span class="pre">get_db</span></code>
function we created above:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">make_dicts</span><span class="p">(</span><span class="n">cursor</span><span class="p">,</span> <span class="n">row</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">dict</span><span class="p">((</span><span class="n">cursor</span><span class="o">.</span><span class="n">description</span><span class="p">[</span><span class="n">idx</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="n">value</span><span class="p">)</span>
<span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">row</span><span class="p">))</span>
<span class="n">db</span><span class="o">.</span><span class="n">row_factory</span> <span class="o">=</span> <span class="n">make_dicts</span>
</pre></div>
</div>
<p>This will make the sqlite3 module return dicts for this database connection, which are much nicer to deal with. Even more simply, we could place this in <code class="docutils literal notranslate"><span class="pre">get_db</span></code> instead:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">db</span><span class="o">.</span><span class="n">row_factory</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">Row</span>
</pre></div>
</div>
<p>This would use Row objects rather than dicts to return the results of queries. These are <code class="docutils literal notranslate"><span class="pre">namedtuple</span></code> s, so we can access them either by index or by key. For example, assuming we have a <code class="docutils literal notranslate"><span class="pre">sqlite3.Row</span></code> called <code class="docutils literal notranslate"><span class="pre">r</span></code> for the rows <code class="docutils literal notranslate"><span class="pre">id</span></code>, <code class="docutils literal notranslate"><span class="pre">FirstName</span></code>, <code class="docutils literal notranslate"><span class="pre">LastName</span></code>, and <code class="docutils literal notranslate"><span class="pre">MiddleInitial</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="c1"># You can get values based on the row&#39;s name</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="p">[</span><span class="s1">&#39;FirstName&#39;</span><span class="p">]</span>
<span class="go">John</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c1"># Or, you can get them based on index</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="go">John</span>
<span class="go"># Row objects are also iterable:</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">r</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="go">1</span>
<span class="go">John</span>
<span class="go">Doe</span>
<span class="go">M</span>
</pre></div>
</div>
<p>Additionally, it is a good idea to provide a query function that combines
getting the cursor, executing and fetching the results:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">query_db</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(),</span> <span class="n">one</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">get_db</span><span class="p">()</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span>
<span class="n">rv</span> <span class="o">=</span> <span class="n">cur</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
<span class="n">cur</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">return</span> <span class="p">(</span><span class="n">rv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">rv</span> <span class="k">else</span> <span class="kc">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">one</span> <span class="k">else</span> <span class="n">rv</span>
</pre></div>
</div>
<p>This handy little function, in combination with a row factory, makes
working with the database much more pleasant than it is by just using the
raw cursor and connection objects.</p>
<p>Here is how you can use it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">user</span> <span class="ow">in</span> <span class="n">query_db</span><span class="p">(</span><span class="s1">&#39;select * from users&#39;</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="n">user</span><span class="p">[</span><span class="s1">&#39;username&#39;</span><span class="p">],</span> <span class="s1">&#39;has the id&#39;</span><span class="p">,</span> <span class="n">user</span><span class="p">[</span><span class="s1">&#39;user_id&#39;</span><span class="p">])</span>
</pre></div>
</div>
<p>Or if you just want a single result:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">user</span> <span class="o">=</span> <span class="n">query_db</span><span class="p">(</span><span class="s1">&#39;select * from users where username = ?&#39;</span><span class="p">,</span>
<span class="p">[</span><span class="n">the_username</span><span class="p">],</span> <span class="n">one</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">if</span> <span class="n">user</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;No such user&#39;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">the_username</span><span class="p">,</span> <span class="s1">&#39;has the id&#39;</span><span class="p">,</span> <span class="n">user</span><span class="p">[</span><span class="s1">&#39;user_id&#39;</span><span class="p">])</span>
</pre></div>
</div>
<p>To pass variable parts to the SQL statement, use a question mark in the
statement and pass in the arguments as a list. Never directly add them to
the SQL statement with string formatting because this makes it possible
to attack the application using <a class="reference external" href="https://en.wikipedia.org/wiki/SQL_injection">SQL Injections</a>.</p>
</section>
<section id="initial-schemas">
<h2>Initial Schemas<a class="headerlink" href="#initial-schemas" title="Link to this heading"></a></h2>
<p>Relational databases need schemas, so applications often ship a
<code class="code docutils literal notranslate"><span class="pre">schema.sql</span></code> file that creates the database. Its a good idea to provide
a function that creates the database based on that schema. This function
can do that for you:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">init_db</span><span class="p">():</span>
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">app_context</span><span class="p">():</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">get_db</span><span class="p">()</span>
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">open_resource</span><span class="p">(</span><span class="s1">&#39;schema.sql&#39;</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="s1">&#39;r&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">db</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span><span class="o">.</span><span class="n">executescript</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
<span class="n">db</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</pre></div>
</div>
<p>You can then create such a database from the Python shell:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication</span><span class="w"> </span><span class="kn">import</span> <span class="n">init_db</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">init_db</span><span class="p">()</span>
</pre></div>
</div>
</section>
</section>
@ -106,20 +194,30 @@ for instance should be careful not to access it).</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"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Using SQLite 3 with Flask</a><ul>
<li><a class="reference internal" href="#connect-on-demand">Connect on Demand</a></li>
<li><a class="reference internal" href="#easy-querying">Easy Querying</a></li>
<li><a class="reference internal" href="#initial-schemas">Initial Schemas</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="methodoverrides.html" title="previous chapter">Adding HTTP Method Overrides</a>
<li>Next: <a href="celery.html" title="next chapter">Background Tasks with Celery</a></ul>
<li>Previous: <a href="urlprocessors.html" title="previous chapter">Using URL Processors</a>
<li>Next: <a href="sqlalchemy.html" title="next chapter">SQLAlchemy in Flask</a></ul>
</li>
</ul>
</li>
@ -143,4 +241,4 @@ for instance should be careful not to access it).</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Single-Page Applications &#8212; Flask Documentation (3.2.x)</title>
<title>Streaming Contents &#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="Security Considerations" href="../web-security.html" />
<link rel="prev" title="Subclassing Flask" href="subclassing.html" />
<link rel="next" title="Deferred Request Callbacks" href="deferredcallbacks.html" />
<link rel="prev" title="Adding a favicon" href="favicon.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,45 +28,94 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="../web-security.html" title="Security Considerations"
<a href="deferredcallbacks.html" title="Deferred Request Callbacks"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="subclassing.html" title="Subclassing Flask"
<a href="favicon.html" title="Adding a favicon"
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="">Single-Page Applications</a></li>
<li class="nav-item nav-item-this"><a href="">Streaming Contents</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="single-page-applications">
<h1>Single-Page Applications<a class="headerlink" href="#single-page-applications" title="Link to this heading"></a></h1>
<p>Flask can be used to serve Single-Page Applications (SPA) by placing static
files produced by your frontend framework in a subfolder inside of your
project. You will also need to create a catch-all endpoint that routes all
requests to your SPA.</p>
<p>The following example demonstrates how to serve an SPA along with an API:</p>
<div class="highlight-default 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">jsonify</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="n">static_folder</span><span class="o">=</span><span class="s1">&#39;app&#39;</span><span class="p">,</span> <span class="n">static_url_path</span><span class="o">=</span><span class="s2">&quot;/app&quot;</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="s2">&quot;/heartbeat&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">heartbeat</span><span class="p">():</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">({</span><span class="s2">&quot;status&quot;</span><span class="p">:</span> <span class="s2">&quot;healthy&quot;</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="n">defaults</span><span class="o">=</span><span class="p">{</span><span class="s1">&#39;path&#39;</span><span class="p">:</span> <span class="s1">&#39;&#39;</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;/&lt;path:path&gt;&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">catch_all</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
<span class="k">return</span> <span class="n">app</span><span class="o">.</span><span class="n">send_static_file</span><span class="p">(</span><span class="s2">&quot;index.html&quot;</span><span class="p">)</span>
<section id="streaming-contents">
<h1>Streaming Contents<a class="headerlink" href="#streaming-contents" title="Link to this heading"></a></h1>
<p>Sometimes you want to send an enormous amount of data to the client, much
more than you want to keep in memory. When you are generating the data on
the fly though, how do you send that back to the client without the
roundtrip to the filesystem?</p>
<p>The answer is by using generators and direct responses.</p>
<section id="basic-usage">
<h2>Basic Usage<a class="headerlink" href="#basic-usage" title="Link to this heading"></a></h2>
<p>This is a basic view function that generates a lot of CSV data on the fly.
The trick is to have an inner function that uses a generator to generate
data and to then invoke that function and pass it to a response object:</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;/large.csv&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate_large_csv</span><span class="p">():</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate</span><span class="p">():</span>
<span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">iter_all_rows</span><span class="p">():</span>
<span class="k">yield</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="s1">&#39;,&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">row</span><span class="p">)</span><span class="si">}</span><span class="se">\n</span><span class="s2">&quot;</span>
<span class="k">return</span> <span class="n">generate</span><span class="p">(),</span> <span class="p">{</span><span class="s2">&quot;Content-Type&quot;</span><span class="p">:</span> <span class="s2">&quot;text/csv&quot;</span><span class="p">}</span>
</pre></div>
</div>
<p>Each <code class="docutils literal notranslate"><span class="pre">yield</span></code> expression is directly sent to the browser. Note though
that some WSGI middlewares might break streaming, so be careful there in
debug environments with profilers and other things you might have enabled.</p>
</section>
<section id="streaming-from-templates">
<h2>Streaming from Templates<a class="headerlink" href="#streaming-from-templates" title="Link to this heading"></a></h2>
<p>The Jinja2 template engine supports rendering a template piece by
piece, returning an iterator of strings. Flask provides the
<a class="reference internal" href="../api.html#flask.stream_template" title="flask.stream_template"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_template()</span></code></a> and <a class="reference internal" href="../api.html#flask.stream_template_string" title="flask.stream_template_string"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_template_string()</span></code></a>
functions to make this easier to use.</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">stream_template</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/timeline&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">timeline</span><span class="p">():</span>
<span class="k">return</span> <span class="n">stream_template</span><span class="p">(</span><span class="s2">&quot;timeline.html&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>The parts yielded by the render stream tend to match statement blocks in
the template.</p>
</section>
<section id="streaming-with-context">
<h2>Streaming with Context<a class="headerlink" href="#streaming-with-context" title="Link to this heading"></a></h2>
<p>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> will not be active while the generator is
running, because the view has already returned at that point. If you try
to access <code class="docutils literal notranslate"><span class="pre">request</span></code>, youll get a <code class="docutils literal notranslate"><span class="pre">RuntimeError</span></code>.</p>
<p>If your generator function relies on data in <code class="docutils literal notranslate"><span class="pre">request</span></code>, use the
<a class="reference internal" href="../api.html#flask.stream_with_context" title="flask.stream_with_context"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_with_context()</span></code></a> wrapper. This will keep the request
context active during the generator.</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">stream_with_context</span><span class="p">,</span> <span class="n">request</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">markupsafe</span><span class="w"> </span><span class="kn">import</span> <span class="n">escape</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/stream&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">streamed_response</span><span class="p">():</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate</span><span class="p">():</span>
<span class="k">yield</span> <span class="s1">&#39;&lt;p&gt;Hello &#39;</span>
<span class="k">yield</span> <span class="n">escape</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">])</span>
<span class="k">yield</span> <span class="s1">&#39;!&lt;/p&gt;&#39;</span>
<span class="k">return</span> <span class="n">stream_with_context</span><span class="p">(</span><span class="n">generate</span><span class="p">())</span>
</pre></div>
</div>
<p>It can also be used as a decorator.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@stream_with_context</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate</span><span class="p">():</span>
<span class="o">...</span>
<span class="k">return</span> <span class="n">generate</span><span class="p">()</span>
</pre></div>
</div>
<p>The <a class="reference internal" href="../api.html#flask.stream_template" title="flask.stream_template"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_template()</span></code></a> and
<a class="reference internal" href="../api.html#flask.stream_template_string" title="flask.stream_template_string"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_template_string()</span></code></a> functions automatically
use <a class="reference internal" href="../api.html#flask.stream_with_context" title="flask.stream_with_context"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_with_context()</span></code></a> if a request is active.</p>
</section>
</section>
@ -77,20 +126,30 @@ requests to your SPA.</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"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Streaming Contents</a><ul>
<li><a class="reference internal" href="#basic-usage">Basic Usage</a></li>
<li><a class="reference internal" href="#streaming-from-templates">Streaming from Templates</a></li>
<li><a class="reference internal" href="#streaming-with-context">Streaming with Context</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="subclassing.html" title="previous chapter">Subclassing Flask</a>
<li>Next: <a href="../web-security.html" title="next chapter">Security Considerations</a></ul>
<li>Previous: <a href="favicon.html" title="previous chapter">Adding a favicon</a>
<li>Next: <a href="deferredcallbacks.html" title="next chapter">Deferred Request Callbacks</a></ul>
</li>
</ul>
</li>
@ -114,4 +173,4 @@ requests to your SPA.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>SQLAlchemy in Flask &#8212; Flask Documentation (3.2.x)</title>
<title>Subclassing Flask &#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="Uploading Files" href="fileuploads.html" />
<link rel="prev" title="Using SQLite 3 with Flask" href="sqlite3.html" />
<link rel="next" title="Single-Page Applications" href="singlepageapplications.html" />
<link rel="prev" title="Background Tasks with Celery" href="celery.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,218 +28,37 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="fileuploads.html" title="Uploading Files"
<a href="singlepageapplications.html" title="Single-Page Applications"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="sqlite3.html" title="Using SQLite 3 with Flask"
<a href="celery.html" title="Background Tasks with Celery"
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="">SQLAlchemy in Flask</a></li>
<li class="nav-item nav-item-this"><a href="">Subclassing Flask</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="sqlalchemy-in-flask">
<h1>SQLAlchemy in Flask<a class="headerlink" href="#sqlalchemy-in-flask" title="Link to this heading"></a></h1>
<p>Many people prefer <a class="reference external" href="https://www.sqlalchemy.org/">SQLAlchemy</a> for database access. In this case its
encouraged to use a package instead of a module for your flask application
and drop the models into a separate module (<a class="reference internal" href="packages.html"><span class="doc">Large Applications as Packages</span></a>). While that
is not necessary, it makes a lot of sense.</p>
<p>There are four very common ways to use SQLAlchemy. I will outline each
of them here:</p>
<section id="flask-sqlalchemy-extension">
<h2>Flask-SQLAlchemy Extension<a class="headerlink" href="#flask-sqlalchemy-extension" title="Link to this heading"></a></h2>
<p>Because SQLAlchemy is a common database abstraction layer and object
relational mapper that requires a little bit of configuration effort,
there is a Flask extension that handles that for you. This is recommended
if you want to get started quickly.</p>
<p>You can download <a class="reference external" href="https://flask-sqlalchemy.palletsprojects.com/">Flask-SQLAlchemy</a> from <a class="reference external" href="https://pypi.org/project/Flask-SQLAlchemy/">PyPI</a>.</p>
</section>
<section id="declarative">
<h2>Declarative<a class="headerlink" href="#declarative" title="Link to this heading"></a></h2>
<p>The declarative extension in SQLAlchemy is the most recent method of using
SQLAlchemy. It allows you to define tables and models in one go, similar
to how Django works. In addition to the following text I recommend the
official documentation on the <a class="reference external" href="https://docs.sqlalchemy.org/en/latest/orm/extensions/declarative/">declarative</a> extension.</p>
<p>Heres the example <code class="file docutils literal notranslate"><span class="pre">database.py</span></code> module for your application:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_engine</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.orm</span><span class="w"> </span><span class="kn">import</span> <span class="n">scoped_session</span><span class="p">,</span> <span class="n">sessionmaker</span><span class="p">,</span> <span class="n">declarative_base</span>
<span class="n">engine</span> <span class="o">=</span> <span class="n">create_engine</span><span class="p">(</span><span class="s1">&#39;sqlite:////tmp/test.db&#39;</span><span class="p">)</span>
<span class="n">db_session</span> <span class="o">=</span> <span class="n">scoped_session</span><span class="p">(</span><span class="n">sessionmaker</span><span class="p">(</span><span class="n">autocommit</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">autoflush</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">))</span>
<span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>
<span class="n">Base</span><span class="o">.</span><span class="n">query</span> <span class="o">=</span> <span class="n">db_session</span><span class="o">.</span><span class="n">query_property</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="nf">init_db</span><span class="p">():</span>
<span class="c1"># import all modules here that might define models so that</span>
<span class="c1"># they will be registered properly on the metadata. Otherwise</span>
<span class="c1"># you will have to import them first before calling init_db()</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">yourapplication.models</span>
<span class="n">Base</span><span class="o">.</span><span class="n">metadata</span><span class="o">.</span><span class="n">create_all</span><span class="p">(</span><span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">)</span>
<section id="subclassing-flask">
<h1>Subclassing Flask<a class="headerlink" href="#subclassing-flask" title="Link to this heading"></a></h1>
<p>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> class is designed for subclassing.</p>
<p>For example, you may want to override how request parameters are handled to preserve their order:</p>
<div class="highlight-default 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="kn">from</span><span class="w"> </span><span class="nn">werkzeug.datastructures</span><span class="w"> </span><span class="kn">import</span> <span class="n">ImmutableOrderedMultiDict</span>
<span class="k">class</span><span class="w"> </span><span class="nc">MyRequest</span><span class="p">(</span><span class="n">Request</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Request subclass to override request parameter storage&quot;&quot;&quot;</span>
<span class="n">parameter_storage_class</span> <span class="o">=</span> <span class="n">ImmutableOrderedMultiDict</span>
<span class="k">class</span><span class="w"> </span><span class="nc">MyFlask</span><span class="p">(</span><span class="n">Flask</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Flask subclass using the custom request class&quot;&quot;&quot;</span>
<span class="n">request_class</span> <span class="o">=</span> <span class="n">MyRequest</span>
</pre></div>
</div>
<p>To define your models, just subclass the <code class="code docutils literal notranslate"><span class="pre">Base</span></code> class that was created by
the code above. If you are wondering why we dont have to care about
threads here (like we did in the SQLite3 example above with the
<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> object): thats because SQLAlchemy does that for us
already with the <a class="reference external" href="https://docs.sqlalchemy.org/en/20/orm/contextual.html#sqlalchemy.orm.scoped_session" title="(in SQLAlchemy v2.0)"><code class="xref py py-class docutils literal notranslate"><span class="pre">scoped_session</span></code></a>.</p>
<p>To use SQLAlchemy in a declarative way with your application, you just
have to put the following code into your application module. Flask will
automatically remove database sessions at the end of the request or
when the application shuts down:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">db_session</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">teardown_appcontext</span>
<span class="k">def</span><span class="w"> </span><span class="nf">shutdown_session</span><span class="p">(</span><span class="n">exception</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="n">db_session</span><span class="o">.</span><span class="n">remove</span><span class="p">()</span>
</pre></div>
</div>
<p>Here is an example model (put this into <code class="file docutils literal notranslate"><span class="pre">models.py</span></code>, e.g.):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">Column</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">String</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">Base</span>
<span class="k">class</span><span class="w"> </span><span class="nc">User</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s1">&#39;users&#39;</span>
<span class="nb">id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">name</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">email</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">String</span><span class="p">(</span><span class="mi">120</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="n">email</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="sa">f</span><span class="s1">&#39;&lt;User </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">!r}</span><span class="s1">&gt;&#39;</span>
</pre></div>
</div>
<p>To create the database you can use the <code class="code docutils literal notranslate"><span class="pre">init_db</span></code> function:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">init_db</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">init_db</span><span class="p">()</span>
</pre></div>
</div>
<p>You can insert entries into the database like this:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">db_session</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.models</span><span class="w"> </span><span class="kn">import</span> <span class="n">User</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">u</span> <span class="o">=</span> <span class="n">User</span><span class="p">(</span><span class="s1">&#39;admin&#39;</span><span class="p">,</span> <span class="s1">&#39;admin@localhost&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db_session</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">u</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db_session</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</pre></div>
</div>
<p>Querying is simple as well:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
<span class="go">[&lt;User &#39;admin&#39;&gt;]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">User</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">User</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s1">&#39;admin&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="go">&lt;User &#39;admin&#39;&gt;</span>
</pre></div>
</div>
</section>
<section id="manual-object-relational-mapping">
<h2>Manual Object Relational Mapping<a class="headerlink" href="#manual-object-relational-mapping" title="Link to this heading"></a></h2>
<p>Manual object relational mapping has a few upsides and a few downsides
versus the declarative approach from above. The main difference is that
you define tables and classes separately and map them together. Its more
flexible but a little more to type. In general it works like the
declarative approach, so make sure to also split up your application into
multiple modules in a package.</p>
<p>Here is an example <code class="file docutils literal notranslate"><span class="pre">database.py</span></code> module for your application:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_engine</span><span class="p">,</span> <span class="n">MetaData</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.orm</span><span class="w"> </span><span class="kn">import</span> <span class="n">scoped_session</span><span class="p">,</span> <span class="n">sessionmaker</span>
<span class="n">engine</span> <span class="o">=</span> <span class="n">create_engine</span><span class="p">(</span><span class="s1">&#39;sqlite:////tmp/test.db&#39;</span><span class="p">)</span>
<span class="n">metadata</span> <span class="o">=</span> <span class="n">MetaData</span><span class="p">()</span>
<span class="n">db_session</span> <span class="o">=</span> <span class="n">scoped_session</span><span class="p">(</span><span class="n">sessionmaker</span><span class="p">(</span><span class="n">autocommit</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">autoflush</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">))</span>
<span class="k">def</span><span class="w"> </span><span class="nf">init_db</span><span class="p">():</span>
<span class="n">metadata</span><span class="o">.</span><span class="n">create_all</span><span class="p">(</span><span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">)</span>
</pre></div>
</div>
<p>As in the declarative approach, you need to close the session after
each request or application context shutdown. Put this into your
application module:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">db_session</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">teardown_appcontext</span>
<span class="k">def</span><span class="w"> </span><span class="nf">shutdown_session</span><span class="p">(</span><span class="n">exception</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="n">db_session</span><span class="o">.</span><span class="n">remove</span><span class="p">()</span>
</pre></div>
</div>
<p>Here is an example table and model (put this into <code class="file docutils literal notranslate"><span class="pre">models.py</span></code>):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">Table</span><span class="p">,</span> <span class="n">Column</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">String</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy.orm</span><span class="w"> </span><span class="kn">import</span> <span class="n">mapper</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication.database</span><span class="w"> </span><span class="kn">import</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">db_session</span>
<span class="k">class</span><span class="w"> </span><span class="nc">User</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="n">query</span> <span class="o">=</span> <span class="n">db_session</span><span class="o">.</span><span class="n">query_property</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="o">.</span><span class="n">email</span> <span class="o">=</span> <span class="n">email</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="sa">f</span><span class="s1">&#39;&lt;User </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">!r}</span><span class="s1">&gt;&#39;</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s1">&#39;users&#39;</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">&#39;id&#39;</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="kc">True</span><span class="p">),</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">50</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="kc">True</span><span class="p">),</span>
<span class="n">Column</span><span class="p">(</span><span class="s1">&#39;email&#39;</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mi">120</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="p">)</span>
<span class="n">mapper</span><span class="p">(</span><span class="n">User</span><span class="p">,</span> <span class="n">users</span><span class="p">)</span>
</pre></div>
</div>
<p>Querying and inserting works exactly the same as in the example above.</p>
</section>
<section id="sql-abstraction-layer">
<h2>SQL Abstraction Layer<a class="headerlink" href="#sql-abstraction-layer" title="Link to this heading"></a></h2>
<p>If you just want to use the database system (and SQL) abstraction layer
you basically only need the engine:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">create_engine</span><span class="p">,</span> <span class="n">MetaData</span><span class="p">,</span> <span class="n">Table</span>
<span class="n">engine</span> <span class="o">=</span> <span class="n">create_engine</span><span class="p">(</span><span class="s1">&#39;sqlite:////tmp/test.db&#39;</span><span class="p">)</span>
<span class="n">metadata</span> <span class="o">=</span> <span class="n">MetaData</span><span class="p">(</span><span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">)</span>
</pre></div>
</div>
<p>Then you can either declare the tables in your code like in the examples
above, or automatically load them:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">sqlalchemy</span><span class="w"> </span><span class="kn">import</span> <span class="n">Table</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s1">&#39;users&#39;</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">autoload</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div>
</div>
<p>To insert data you can use the <code class="code docutils literal notranslate"><span class="pre">insert</span></code> method. We have to get a
connection first so that we can use a transaction:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">con</span> <span class="o">=</span> <span class="n">engine</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">con</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">insert</span><span class="p">(),</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;admin&#39;</span><span class="p">,</span> <span class="n">email</span><span class="o">=</span><span class="s1">&#39;admin@localhost&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>SQLAlchemy will automatically commit for us.</p>
<p>To query your database, you use the engine directly or use a connection:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">users</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">execute</span><span class="p">()</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="go">(1, &#39;admin&#39;, &#39;admin@localhost&#39;)</span>
</pre></div>
</div>
<p>These results are also dict-like tuples:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">r</span> <span class="o">=</span> <span class="n">users</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="n">users</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">execute</span><span class="p">()</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">]</span>
<span class="go">&#39;admin&#39;</span>
</pre></div>
</div>
<p>You can also pass strings of SQL statements to the
<code class="xref py py-meth docutils literal notranslate"><span class="pre">execute()</span></code> method:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">engine</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s1">&#39;select * from users where id = :1&#39;</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">])</span><span class="o">.</span><span class="n">first</span><span class="p">()</span>
<span class="go">(1, &#39;admin&#39;, &#39;admin@localhost&#39;)</span>
</pre></div>
</div>
<p>For more information about SQLAlchemy, head over to the
<a class="reference external" href="https://www.sqlalchemy.org/">website</a>.</p>
</section>
<p>This is the recommended approach for overriding or augmenting Flasks internal functionality.</p>
</section>
@ -250,31 +69,20 @@ connection first so that we can use a transaction:</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"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">SQLAlchemy in Flask</a><ul>
<li><a class="reference internal" href="#flask-sqlalchemy-extension">Flask-SQLAlchemy Extension</a></li>
<li><a class="reference internal" href="#declarative">Declarative</a></li>
<li><a class="reference internal" href="#manual-object-relational-mapping">Manual Object Relational Mapping</a></li>
<li><a class="reference internal" href="#sql-abstraction-layer">SQL Abstraction Layer</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="sqlite3.html" title="previous chapter">Using SQLite 3 with Flask</a>
<li>Next: <a href="fileuploads.html" title="next chapter">Uploading Files</a></ul>
<li>Previous: <a href="celery.html" title="previous chapter">Background Tasks with Celery</a>
<li>Next: <a href="singlepageapplications.html" title="next chapter">Single-Page Applications</a></ul>
</li>
</ul>
</li>
@ -298,4 +106,4 @@ connection first so that we can use a transaction:</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Using SQLite 3 with Flask &#8212; Flask Documentation (3.2.x)</title>
<title>Template Inheritance &#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="SQLAlchemy in Flask" href="sqlalchemy.html" />
<link rel="prev" title="Using URL Processors" href="urlprocessors.html" />
<link rel="next" title="Message Flashing" href="flashing.html" />
<link rel="prev" title="Form Validation with WTForms" href="wtforms.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,161 +28,80 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="sqlalchemy.html" title="SQLAlchemy in Flask"
<a href="flashing.html" title="Message Flashing"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="urlprocessors.html" title="Using URL Processors"
<a href="wtforms.html" title="Form Validation with WTForms"
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="">Using SQLite 3 with Flask</a></li>
<li class="nav-item nav-item-this"><a href="">Template Inheritance</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="using-sqlite-3-with-flask">
<h1>Using SQLite 3 with Flask<a class="headerlink" href="#using-sqlite-3-with-flask" title="Link to this heading"></a></h1>
<p>In Flask you can easily implement the opening of database connections on
demand and closing them when the context dies (usually at the end of the
request).</p>
<p>Here is a simple example of how you can use SQLite 3 with Flask:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">sqlite3</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">g</span>
<span class="n">DATABASE</span> <span class="o">=</span> <span class="s1">&#39;/path/to/database.db&#39;</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_db</span><span class="p">():</span>
<span class="n">db</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="s1">&#39;_database&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="k">if</span> <span class="n">db</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">g</span><span class="o">.</span><span class="n">_database</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">DATABASE</span><span class="p">)</span>
<span class="k">return</span> <span class="n">db</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">teardown_appcontext</span>
<span class="k">def</span><span class="w"> </span><span class="nf">close_connection</span><span class="p">(</span><span class="n">exception</span><span class="p">):</span>
<span class="n">db</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="s1">&#39;_database&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="k">if</span> <span class="n">db</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">db</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p>Now, to use the database, the application must either have an active
application context (which is always true if there is a request in flight)
or create an application context itself. At that point the <code class="docutils literal notranslate"><span class="pre">get_db</span></code>
function can be used to get the current database connection. Whenever the
context is destroyed the database connection will be terminated.</p>
<p>Example:</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;/&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">():</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">get_db</span><span class="p">()</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
<span class="o">...</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Please keep in mind that the teardown request and appcontext functions
are always executed, even if a before-request handler failed or was
never executed. Because of this we have to make sure here that the
database is there before we close it.</p>
</div>
<section id="connect-on-demand">
<h2>Connect on Demand<a class="headerlink" href="#connect-on-demand" title="Link to this heading"></a></h2>
<p>The upside of this approach (connecting on first use) is that this will
only open the connection if truly necessary. If you want to use this
code outside a request context you can use it in a Python shell by opening
the application context by hand:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">app_context</span><span class="p">():</span>
<span class="c1"># now you can use get_db()</span>
<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>
</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="easy-querying">
<h2>Easy Querying<a class="headerlink" href="#easy-querying" title="Link to this heading"></a></h2>
<p>Now in each request handling function you can access <code class="code docutils literal notranslate"><span class="pre">get_db()</span></code> to get the
current open database connection. To simplify working with SQLite, a
row factory function is useful. It is executed for every result returned
from the database to convert the result. For instance, in order to get
dictionaries instead of tuples, this could be inserted into the <code class="docutils literal notranslate"><span class="pre">get_db</span></code>
function we created above:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">make_dicts</span><span class="p">(</span><span class="n">cursor</span><span class="p">,</span> <span class="n">row</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">dict</span><span class="p">((</span><span class="n">cursor</span><span class="o">.</span><span class="n">description</span><span class="p">[</span><span class="n">idx</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="n">value</span><span class="p">)</span>
<span class="k">for</span> <span class="n">idx</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">row</span><span class="p">))</span>
<span class="n">db</span><span class="o">.</span><span class="n">row_factory</span> <span class="o">=</span> <span class="n">make_dicts</span>
</pre></div>
</div>
<p>This will make the sqlite3 module return dicts for this database connection, which are much nicer to deal with. Even more simply, we could place this in <code class="docutils literal notranslate"><span class="pre">get_db</span></code> instead:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">db</span><span class="o">.</span><span class="n">row_factory</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">Row</span>
</pre></div>
</div>
<p>This would use Row objects rather than dicts to return the results of queries. These are <code class="docutils literal notranslate"><span class="pre">namedtuple</span></code> s, so we can access them either by index or by key. For example, assuming we have a <code class="docutils literal notranslate"><span class="pre">sqlite3.Row</span></code> called <code class="docutils literal notranslate"><span class="pre">r</span></code> for the rows <code class="docutils literal notranslate"><span class="pre">id</span></code>, <code class="docutils literal notranslate"><span class="pre">FirstName</span></code>, <code class="docutils literal notranslate"><span class="pre">LastName</span></code>, and <code class="docutils literal notranslate"><span class="pre">MiddleInitial</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="c1"># You can get values based on the row&#39;s name</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="p">[</span><span class="s1">&#39;FirstName&#39;</span><span class="p">]</span>
<span class="go">John</span>
<span class="gp">&gt;&gt;&gt; </span><span class="c1"># Or, you can get them based on index</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">r</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="go">John</span>
<span class="go"># Row objects are also iterable:</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">r</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="go">1</span>
<span class="go">John</span>
<span class="go">Doe</span>
<span class="go">M</span>
</pre></div>
</div>
<p>Additionally, it is a good idea to provide a query function that combines
getting the cursor, executing and fetching the results:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">query_db</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(),</span> <span class="n">one</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">get_db</span><span class="p">()</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span>
<span class="n">rv</span> <span class="o">=</span> <span class="n">cur</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
<span class="n">cur</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">return</span> <span class="p">(</span><span class="n">rv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">rv</span> <span class="k">else</span> <span class="kc">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">one</span> <span class="k">else</span> <span class="n">rv</span>
</pre></div>
</div>
<p>This handy little function, in combination with a row factory, makes
working with the database much more pleasant than it is by just using the
raw cursor and connection objects.</p>
<p>Here is how you can use it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">user</span> <span class="ow">in</span> <span class="n">query_db</span><span class="p">(</span><span class="s1">&#39;select * from users&#39;</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="n">user</span><span class="p">[</span><span class="s1">&#39;username&#39;</span><span class="p">],</span> <span class="s1">&#39;has the id&#39;</span><span class="p">,</span> <span class="n">user</span><span class="p">[</span><span class="s1">&#39;user_id&#39;</span><span class="p">])</span>
</pre></div>
</div>
<p>Or if you just want a single result:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">user</span> <span class="o">=</span> <span class="n">query_db</span><span class="p">(</span><span class="s1">&#39;select * from users where username = ?&#39;</span><span class="p">,</span>
<span class="p">[</span><span class="n">the_username</span><span class="p">],</span> <span class="n">one</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">if</span> <span class="n">user</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;No such user&#39;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">the_username</span><span class="p">,</span> <span class="s1">&#39;has the id&#39;</span><span class="p">,</span> <span class="n">user</span><span class="p">[</span><span class="s1">&#39;user_id&#39;</span><span class="p">])</span>
</pre></div>
</div>
<p>To pass variable parts to the SQL statement, use a question mark in the
statement and pass in the arguments as a list. Never directly add them to
the SQL statement with string formatting because this makes it possible
to attack the application using <a class="reference external" href="https://en.wikipedia.org/wiki/SQL_injection">SQL Injections</a>.</p>
</section>
<section id="initial-schemas">
<h2>Initial Schemas<a class="headerlink" href="#initial-schemas" title="Link to this heading"></a></h2>
<p>Relational databases need schemas, so applications often ship a
<code class="code docutils literal notranslate"><span class="pre">schema.sql</span></code> file that creates the database. Its a good idea to provide
a function that creates the database based on that schema. This function
can do that for you:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">init_db</span><span class="p">():</span>
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">app_context</span><span class="p">():</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">get_db</span><span class="p">()</span>
<span class="k">with</span> <span class="n">app</span><span class="o">.</span><span class="n">open_resource</span><span class="p">(</span><span class="s1">&#39;schema.sql&#39;</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="s1">&#39;r&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">db</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span><span class="o">.</span><span class="n">executescript</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
<span class="n">db</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
</pre></div>
</div>
<p>You can then create such a database from the Python shell:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span><span class="w"> </span><span class="nn">yourapplication</span><span class="w"> </span><span class="kn">import</span> <span class="n">init_db</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">init_db</span><span class="p">()</span>
<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>
</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>
</section>
</section>
@ -194,19 +113,18 @@ can do that for you:</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"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Using SQLite 3 with Flask</a><ul>
<li><a class="reference internal" href="#connect-on-demand">Connect on Demand</a></li>
<li><a class="reference internal" href="#easy-querying">Easy Querying</a></li>
<li><a class="reference internal" href="#initial-schemas">Initial Schemas</a></li>
<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>
</ul>
</li>
</ul>
@ -216,8 +134,8 @@ can do that for you:</p>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="urlprocessors.html" title="previous chapter">Using URL Processors</a>
<li>Next: <a href="sqlalchemy.html" title="next chapter">SQLAlchemy in 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>
</ul>
</li>
@ -241,4 +159,4 @@ can do that for you:</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Streaming Contents &#8212; Flask Documentation (3.2.x)</title>
<title>Using URL Processors &#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="Deferred Request Callbacks" href="deferredcallbacks.html" />
<link rel="prev" title="Adding a favicon" href="favicon.html" />
<link rel="next" title="Using SQLite 3 with Flask" href="sqlite3.html" />
<link rel="prev" title="Application Dispatching" href="appdispatch.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,93 +28,145 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="deferredcallbacks.html" title="Deferred Request Callbacks"
<a href="sqlite3.html" title="Using SQLite 3 with Flask"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="favicon.html" title="Adding a favicon"
<a href="appdispatch.html" title="Application Dispatching"
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="">Streaming Contents</a></li>
<li class="nav-item nav-item-this"><a href="">Using URL Processors</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="streaming-contents">
<h1>Streaming Contents<a class="headerlink" href="#streaming-contents" title="Link to this heading"></a></h1>
<p>Sometimes you want to send an enormous amount of data to the client, much
more than you want to keep in memory. When you are generating the data on
the fly though, how do you send that back to the client without the
roundtrip to the filesystem?</p>
<p>The answer is by using generators and direct responses.</p>
<section id="basic-usage">
<h2>Basic Usage<a class="headerlink" href="#basic-usage" title="Link to this heading"></a></h2>
<p>This is a basic view function that generates a lot of CSV data on the fly.
The trick is to have an inner function that uses a generator to generate
data and to then invoke that function and pass it to a response object:</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;/large.csv&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate_large_csv</span><span class="p">():</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate</span><span class="p">():</span>
<span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">iter_all_rows</span><span class="p">():</span>
<span class="k">yield</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="s1">&#39;,&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">row</span><span class="p">)</span><span class="si">}</span><span class="se">\n</span><span class="s2">&quot;</span>
<span class="k">return</span> <span class="n">generate</span><span class="p">(),</span> <span class="p">{</span><span class="s2">&quot;Content-Type&quot;</span><span class="p">:</span> <span class="s2">&quot;text/csv&quot;</span><span class="p">}</span>
</pre></div>
</div>
<p>Each <code class="docutils literal notranslate"><span class="pre">yield</span></code> expression is directly sent to the browser. Note though
that some WSGI middlewares might break streaming, so be careful there in
debug environments with profilers and other things you might have enabled.</p>
</section>
<section id="streaming-from-templates">
<h2>Streaming from Templates<a class="headerlink" href="#streaming-from-templates" title="Link to this heading"></a></h2>
<p>The Jinja2 template engine supports rendering a template piece by
piece, returning an iterator of strings. Flask provides the
<a class="reference internal" href="../api.html#flask.stream_template" title="flask.stream_template"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_template()</span></code></a> and <a class="reference internal" href="../api.html#flask.stream_template_string" title="flask.stream_template_string"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_template_string()</span></code></a>
functions to make this easier to use.</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">stream_template</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/timeline&quot;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">timeline</span><span class="p">():</span>
<span class="k">return</span> <span class="n">stream_template</span><span class="p">(</span><span class="s2">&quot;timeline.html&quot;</span><span class="p">)</span>
</pre></div>
<section id="using-url-processors">
<h1>Using URL Processors<a class="headerlink" href="#using-url-processors" title="Link to this heading"></a></h1>
<details class="changelog">
<summary>Changelog</summary><div class="versionadded">
<p><span class="versionmodified added">Added in version 0.7.</span></p>
</div>
<p>The parts yielded by the render stream tend to match statement blocks in
the template.</p>
</section>
<section id="streaming-with-context">
<h2>Streaming with Context<a class="headerlink" href="#streaming-with-context" title="Link to this heading"></a></h2>
<p>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> will not be active while the generator is
running, because the view has already returned at that point. If you try
to access <code class="docutils literal notranslate"><span class="pre">request</span></code>, youll get a <code class="docutils literal notranslate"><span class="pre">RuntimeError</span></code>.</p>
<p>If your generator function relies on data in <code class="docutils literal notranslate"><span class="pre">request</span></code>, use the
<a class="reference internal" href="../api.html#flask.stream_with_context" title="flask.stream_with_context"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_with_context()</span></code></a> wrapper. This will keep the request
context active during the generator.</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">stream_with_context</span><span class="p">,</span> <span class="n">request</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">markupsafe</span><span class="w"> </span><span class="kn">import</span> <span class="n">escape</span>
</details><p>Flask 0.7 introduces the concept of URL processors. The idea is that you
might have a bunch of resources with common parts in the URL that you
dont always explicitly want to provide. For instance you might have a
bunch of URLs that have the language code in it but you dont want to have
to handle it in every single function yourself.</p>
<p>URL processors are especially helpful when combined with blueprints. We
will handle both application specific URL processors here as well as
blueprint specifics.</p>
<section id="internationalized-application-urls">
<h2>Internationalized Application URLs<a class="headerlink" href="#internationalized-application-urls" title="Link to this heading"></a></h2>
<p>Consider an application like this:</p>
<div class="highlight-default 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">g</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/stream&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">streamed_response</span><span class="p">():</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate</span><span class="p">():</span>
<span class="k">yield</span> <span class="s1">&#39;&lt;p&gt;Hello &#39;</span>
<span class="k">yield</span> <span class="n">escape</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">])</span>
<span class="k">yield</span> <span class="s1">&#39;!&lt;/p&gt;&#39;</span>
<span class="k">return</span> <span class="n">stream_with_context</span><span class="p">(</span><span class="n">generate</span><span class="p">())</span>
</pre></div>
</div>
<p>It can also be used as a decorator.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@stream_with_context</span>
<span class="k">def</span><span class="w"> </span><span class="nf">generate</span><span class="p">():</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;/&lt;lang_code&gt;/&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">(</span><span class="n">lang_code</span><span class="p">):</span>
<span class="n">g</span><span class="o">.</span><span class="n">lang_code</span> <span class="o">=</span> <span class="n">lang_code</span>
<span class="o">...</span>
<span class="k">return</span> <span class="n">generate</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;/&lt;lang_code&gt;/about&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">about</span><span class="p">(</span><span class="n">lang_code</span><span class="p">):</span>
<span class="n">g</span><span class="o">.</span><span class="n">lang_code</span> <span class="o">=</span> <span class="n">lang_code</span>
<span class="o">...</span>
</pre></div>
</div>
<p>This is an awful lot of repetition as you have to handle the language code
setting on the <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> object yourself in every single function.
Sure, a decorator could be used to simplify this, but if you want to
generate URLs from one function to another you would have to still provide
the language code explicitly which can be annoying.</p>
<p>For the latter, this is where <a class="reference internal" href="../api.html#flask.Flask.url_defaults" title="flask.Flask.url_defaults"><code class="xref py py-func docutils literal notranslate"><span class="pre">url_defaults()</span></code></a> functions
come in. They can automatically inject values into a call to
<a class="reference internal" href="../api.html#flask.url_for" title="flask.url_for"><code class="xref py py-func docutils literal notranslate"><span class="pre">url_for()</span></code></a>. The code below checks if the
language code is not yet in the dictionary of URL values and if the
endpoint wants a value named <code class="docutils literal notranslate"><span class="pre">'lang_code'</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@app</span><span class="o">.</span><span class="n">url_defaults</span>
<span class="k">def</span><span class="w"> </span><span class="nf">add_language_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="k">if</span> <span class="s1">&#39;lang_code&#39;</span> <span class="ow">in</span> <span class="n">values</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">g</span><span class="o">.</span><span class="n">lang_code</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">if</span> <span class="n">app</span><span class="o">.</span><span class="n">url_map</span><span class="o">.</span><span class="n">is_endpoint_expecting</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="s1">&#39;lang_code&#39;</span><span class="p">):</span>
<span class="n">values</span><span class="p">[</span><span class="s1">&#39;lang_code&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">g</span><span class="o">.</span><span class="n">lang_code</span>
</pre></div>
</div>
<p>The method <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/routing/#werkzeug.routing.Map.is_endpoint_expecting" title="(in Werkzeug v3.1.x)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">is_endpoint_expecting()</span></code></a> of the URL
map can be used to figure out if it would make sense to provide a language
code for the given endpoint.</p>
<p>The reverse of that function are
<a class="reference internal" href="../api.html#flask.Flask.url_value_preprocessor" title="flask.Flask.url_value_preprocessor"><code class="xref py py-meth docutils literal notranslate"><span class="pre">url_value_preprocessor()</span></code></a>s. They are executed right
after the request was matched and can execute code based on the URL
values. The idea is that they pull information out of the values
dictionary and put it somewhere else:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@app</span><span class="o">.</span><span class="n">url_value_preprocessor</span>
<span class="k">def</span><span class="w"> </span><span class="nf">pull_lang_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="n">g</span><span class="o">.</span><span class="n">lang_code</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;lang_code&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
</pre></div>
</div>
<p>That way you no longer have to do the <code class="code docutils literal notranslate"><span class="pre">lang_code</span></code> assignment to
<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> in every function. You can further improve that by
writing your own decorator that prefixes URLs with the language code, but
the more beautiful solution is using a blueprint. Once the
<code class="docutils literal notranslate"><span class="pre">'lang_code'</span></code> is popped from the values dictionary and it will no longer
be forwarded to the view function reducing the code to this:</p>
<div class="highlight-default 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">g</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">url_defaults</span>
<span class="k">def</span><span class="w"> </span><span class="nf">add_language_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="k">if</span> <span class="s1">&#39;lang_code&#39;</span> <span class="ow">in</span> <span class="n">values</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">g</span><span class="o">.</span><span class="n">lang_code</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">if</span> <span class="n">app</span><span class="o">.</span><span class="n">url_map</span><span class="o">.</span><span class="n">is_endpoint_expecting</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="s1">&#39;lang_code&#39;</span><span class="p">):</span>
<span class="n">values</span><span class="p">[</span><span class="s1">&#39;lang_code&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">g</span><span class="o">.</span><span class="n">lang_code</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">url_value_preprocessor</span>
<span class="k">def</span><span class="w"> </span><span class="nf">pull_lang_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="n">g</span><span class="o">.</span><span class="n">lang_code</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;lang_code&#39;</span><span class="p">,</span> <span class="kc">None</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;/&lt;lang_code&gt;/&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">():</span>
<span class="o">...</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/&lt;lang_code&gt;/about&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">about</span><span class="p">():</span>
<span class="o">...</span>
</pre></div>
</div>
</section>
<section id="internationalized-blueprint-urls">
<h2>Internationalized Blueprint URLs<a class="headerlink" href="#internationalized-blueprint-urls" title="Link to this heading"></a></h2>
<p>Because blueprints can automatically prefix all URLs with a common string
its easy to automatically do that for every function. Furthermore
blueprints can have per-blueprint URL processors which removes a whole lot
of logic from the <a class="reference internal" href="../api.html#flask.Flask.url_defaults" title="flask.Flask.url_defaults"><code class="xref py py-meth docutils literal notranslate"><span class="pre">url_defaults()</span></code></a> function because it no
longer has to check if the URL is really interested in a <code class="docutils literal notranslate"><span class="pre">'lang_code'</span></code>
parameter:</p>
<div class="highlight-default 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">Blueprint</span><span class="p">,</span> <span class="n">g</span>
<span class="n">bp</span> <span class="o">=</span> <span class="n">Blueprint</span><span class="p">(</span><span class="s1">&#39;frontend&#39;</span><span class="p">,</span> <span class="vm">__name__</span><span class="p">,</span> <span class="n">url_prefix</span><span class="o">=</span><span class="s1">&#39;/&lt;lang_code&gt;&#39;</span><span class="p">)</span>
<span class="nd">@bp</span><span class="o">.</span><span class="n">url_defaults</span>
<span class="k">def</span><span class="w"> </span><span class="nf">add_language_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="n">values</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s1">&#39;lang_code&#39;</span><span class="p">,</span> <span class="n">g</span><span class="o">.</span><span class="n">lang_code</span><span class="p">)</span>
<span class="nd">@bp</span><span class="o">.</span><span class="n">url_value_preprocessor</span>
<span class="k">def</span><span class="w"> </span><span class="nf">pull_lang_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="n">g</span><span class="o">.</span><span class="n">lang_code</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;lang_code&#39;</span><span class="p">)</span>
<span class="nd">@bp</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">index</span><span class="p">():</span>
<span class="o">...</span>
<span class="nd">@bp</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/about&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">about</span><span class="p">():</span>
<span class="o">...</span>
</pre></div>
</div>
<p>The <a class="reference internal" href="../api.html#flask.stream_template" title="flask.stream_template"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_template()</span></code></a> and
<a class="reference internal" href="../api.html#flask.stream_template_string" title="flask.stream_template_string"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_template_string()</span></code></a> functions automatically
use <a class="reference internal" href="../api.html#flask.stream_with_context" title="flask.stream_with_context"><code class="xref py py-func docutils literal notranslate"><span class="pre">stream_with_context()</span></code></a> if a request is active.</p>
</section>
</section>
@ -126,19 +178,18 @@ use <a class="reference internal" href="../api.html#flask.stream_with_context" t
<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="#">Streaming Contents</a><ul>
<li><a class="reference internal" href="#basic-usage">Basic Usage</a></li>
<li><a class="reference internal" href="#streaming-from-templates">Streaming from Templates</a></li>
<li><a class="reference internal" href="#streaming-with-context">Streaming with Context</a></li>
<li><a class="reference internal" href="#">Using URL Processors</a><ul>
<li><a class="reference internal" href="#internationalized-application-urls">Internationalized Application URLs</a></li>
<li><a class="reference internal" href="#internationalized-blueprint-urls">Internationalized Blueprint URLs</a></li>
</ul>
</li>
</ul>
@ -148,8 +199,8 @@ use <a class="reference internal" href="../api.html#flask.stream_with_context" t
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="favicon.html" title="previous chapter">Adding a favicon</a>
<li>Next: <a href="deferredcallbacks.html" title="next chapter">Deferred Request Callbacks</a></ul>
<li>Previous: <a href="appdispatch.html" title="previous chapter">Application Dispatching</a>
<li>Next: <a href="sqlite3.html" title="next chapter">Using SQLite 3 with Flask</a></ul>
</li>
</ul>
</li>
@ -173,4 +224,4 @@ use <a class="reference internal" href="../api.html#flask.stream_with_context" t
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>Subclassing Flask &#8212; Flask Documentation (3.2.x)</title>
<title>View Decorators &#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="Single-Page Applications" href="singlepageapplications.html" />
<link rel="prev" title="Background Tasks with Celery" href="celery.html" />
<link rel="next" title="Form Validation with WTForms" href="wtforms.html" />
<link rel="prev" title="Caching" href="caching.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
@ -28,37 +28,186 @@
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="singlepageapplications.html" title="Single-Page Applications"
<a href="wtforms.html" title="Form Validation with WTForms"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="celery.html" title="Background Tasks with Celery"
<a href="caching.html" title="Caching"
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="">Subclassing Flask</a></li>
<li class="nav-item nav-item-this"><a href="">View Decorators</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="subclassing-flask">
<h1>Subclassing Flask<a class="headerlink" href="#subclassing-flask" title="Link to this heading"></a></h1>
<p>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> class is designed for subclassing.</p>
<p>For example, you may want to override how request parameters are handled to preserve their order:</p>
<div class="highlight-default 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="kn">from</span><span class="w"> </span><span class="nn">werkzeug.datastructures</span><span class="w"> </span><span class="kn">import</span> <span class="n">ImmutableOrderedMultiDict</span>
<span class="k">class</span><span class="w"> </span><span class="nc">MyRequest</span><span class="p">(</span><span class="n">Request</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Request subclass to override request parameter storage&quot;&quot;&quot;</span>
<span class="n">parameter_storage_class</span> <span class="o">=</span> <span class="n">ImmutableOrderedMultiDict</span>
<span class="k">class</span><span class="w"> </span><span class="nc">MyFlask</span><span class="p">(</span><span class="n">Flask</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Flask subclass using the custom request class&quot;&quot;&quot;</span>
<span class="n">request_class</span> <span class="o">=</span> <span class="n">MyRequest</span>
<section id="view-decorators">
<h1>View Decorators<a class="headerlink" href="#view-decorators" title="Link to this heading"></a></h1>
<p>Python has a really interesting feature called function decorators. This
allows some really neat things for web applications. Because each view in
Flask is a function, decorators can be used to inject additional
functionality to one or more functions. The <a class="reference internal" href="../api.html#flask.Flask.route" title="flask.Flask.route"><code class="xref py py-meth docutils literal notranslate"><span class="pre">route()</span></code></a>
decorator is the one you probably used already. But there are use cases
for implementing your own decorator. For instance, imagine you have a
view that should only be used by people that are logged in. If a user
goes to the site and is not logged in, they should be redirected to the
login page. This is a good example of a use case where a decorator is an
excellent solution.</p>
<section id="login-required-decorator">
<h2>Login Required Decorator<a class="headerlink" href="#login-required-decorator" title="Link to this heading"></a></h2>
<p>So lets implement such a decorator. A decorator is a function that
wraps and replaces another function. Since the original function is
replaced, you need to remember to copy the original functions information
to the new function. Use <a class="reference external" href="https://docs.python.org/3/library/functools.html#functools.wraps" title="(in Python v3.13)"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.wraps()</span></code></a> to handle this for you.</p>
<p>This example assumes that the login page is called <code class="docutils literal notranslate"><span class="pre">'login'</span></code> and that
the current user is stored in <code class="docutils literal notranslate"><span class="pre">g.user</span></code> and is <code class="docutils literal notranslate"><span class="pre">None</span></code> if there is no-one
logged in.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">functools</span><span class="w"> </span><span class="kn">import</span> <span class="n">wraps</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">g</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">redirect</span><span class="p">,</span> <span class="n">url_for</span>
<span class="k">def</span><span class="w"> </span><span class="nf">login_required</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
<span class="nd">@wraps</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">decorated_function</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">if</span> <span class="n">g</span><span class="o">.</span><span class="n">user</span> <span class="ow">is</span> <span class="kc">None</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="nb">next</span><span class="o">=</span><span class="n">request</span><span class="o">.</span><span class="n">url</span><span class="p">))</span>
<span class="k">return</span> <span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">return</span> <span class="n">decorated_function</span>
</pre></div>
</div>
<p>This is the recommended approach for overriding or augmenting Flasks internal functionality.</p>
<p>To use the decorator, apply it as innermost decorator to a view function.
When applying further decorators, always remember
that the <a class="reference internal" href="../api.html#flask.Flask.route" title="flask.Flask.route"><code class="xref py py-meth docutils literal notranslate"><span class="pre">route()</span></code></a> decorator is the outermost.</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;/secret_page&#39;</span><span class="p">)</span>
<span class="nd">@login_required</span>
<span class="k">def</span><span class="w"> </span><span class="nf">secret_page</span><span class="p">():</span>
<span class="k">pass</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The <code class="docutils literal notranslate"><span class="pre">next</span></code> value will exist in <code class="docutils literal notranslate"><span class="pre">request.args</span></code> after a <code class="docutils literal notranslate"><span class="pre">GET</span></code> request for
the login page. Youll have to pass it along when sending the <code class="docutils literal notranslate"><span class="pre">POST</span></code> request
from the login form. You can do this with a hidden input tag, then retrieve it
from <code class="docutils literal notranslate"><span class="pre">request.form</span></code> when logging the user in.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&lt;</span><span class="nb">input</span> <span class="nb">type</span><span class="o">=</span><span class="s2">&quot;hidden&quot;</span> <span class="n">value</span><span class="o">=</span><span class="s2">&quot;{{ request.args.get(&#39;next&#39;, &#39;&#39;) }}&quot;</span><span class="o">/&gt;</span>
</pre></div>
</div>
</div>
</section>
<section id="caching-decorator">
<h2>Caching Decorator<a class="headerlink" href="#caching-decorator" title="Link to this heading"></a></h2>
<p>Imagine you have a view function that does an expensive calculation and
because of that you would like to cache the generated results for a
certain amount of time. A decorator would be nice for that. Were
assuming you have set up a cache like mentioned in <a class="reference internal" href="caching.html"><span class="doc">Caching</span></a>.</p>
<p>Here is an example cache function. It generates the cache key from a
specific prefix (actually a format string) and the current path of the
request. Notice that we are using a function that first creates the
decorator that then decorates the function. Sounds awful? Unfortunately
it is a little bit more complex, but the code should still be
straightforward to read.</p>
<p>The decorated function will then work as follows</p>
<ol class="arabic simple">
<li><p>get the unique cache key for the current request based on the current
path.</p></li>
<li><p>get the value for that key from the cache. If the cache returned
something we will return that value.</p></li>
<li><p>otherwise the original function is called and the return value is
stored in the cache for the timeout provided (by default 5 minutes).</p></li>
</ol>
<p>Here the code:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">functools</span><span class="w"> </span><span class="kn">import</span> <span class="n">wraps</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">request</span>
<span class="k">def</span><span class="w"> </span><span class="nf">cached</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mi">5</span> <span class="o">*</span> <span class="mi">60</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s1">&#39;view/</span><span class="si">{}</span><span class="s1">&#39;</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="nf">decorator</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
<span class="nd">@wraps</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">decorated_function</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="n">cache_key</span> <span class="o">=</span> <span class="n">key</span><span class="o">.</span><span class="n">format</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="n">rv</span> <span class="o">=</span> <span class="n">cache</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">cache_key</span><span class="p">)</span>
<span class="k">if</span> <span class="n">rv</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">return</span> <span class="n">rv</span>
<span class="n">rv</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="n">cache</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">cache_key</span><span class="p">,</span> <span class="n">rv</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="n">timeout</span><span class="p">)</span>
<span class="k">return</span> <span class="n">rv</span>
<span class="k">return</span> <span class="n">decorated_function</span>
<span class="k">return</span> <span class="n">decorator</span>
</pre></div>
</div>
<p>Notice that this assumes an instantiated <code class="docutils literal notranslate"><span class="pre">cache</span></code> object is available, see
<a class="reference internal" href="caching.html"><span class="doc">Caching</span></a>.</p>
</section>
<section id="templating-decorator">
<h2>Templating Decorator<a class="headerlink" href="#templating-decorator" title="Link to this heading"></a></h2>
<p>A common pattern invented by the TurboGears guys a while back is a
templating decorator. The idea of that decorator is that you return a
dictionary with the values passed to the template from the view function
and the template is automatically rendered. With that, the following
three examples do exactly the same:</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;/&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">():</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">&#39;index.html&#39;</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="mi">42</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="nd">@templated</span><span class="p">(</span><span class="s1">&#39;index.html&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">():</span>
<span class="k">return</span> <span class="nb">dict</span><span class="p">(</span><span class="n">value</span><span class="o">=</span><span class="mi">42</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="nd">@templated</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">():</span>
<span class="k">return</span> <span class="nb">dict</span><span class="p">(</span><span class="n">value</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span>
</pre></div>
</div>
<p>As you can see, if no template name is provided it will use the endpoint
of the URL map with dots converted to slashes + <code class="docutils literal notranslate"><span class="pre">'.html'</span></code>. Otherwise
the provided template name is used. When the decorated function returns,
the dictionary returned is passed to the template rendering function. If
<code class="docutils literal notranslate"><span class="pre">None</span></code> is returned, an empty dictionary is assumed, if something else than
a dictionary is returned we return it from the function unchanged. That
way you can still use the redirect function or return simple strings.</p>
<p>Here is the code for that decorator:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">functools</span><span class="w"> </span><span class="kn">import</span> <span class="n">wraps</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">request</span><span class="p">,</span> <span class="n">render_template</span>
<span class="k">def</span><span class="w"> </span><span class="nf">templated</span><span class="p">(</span><span class="n">template</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="nf">decorator</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
<span class="nd">@wraps</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">decorated_function</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="n">template_name</span> <span class="o">=</span> <span class="n">template</span>
<span class="k">if</span> <span class="n">template_name</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">template_name</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">request</span><span class="o">.</span><span class="n">endpoint</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;/&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">.html&quot;</span>
<span class="n">ctx</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">if</span> <span class="n">ctx</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">ctx</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">elif</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
<span class="k">return</span> <span class="n">ctx</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="n">template_name</span><span class="p">,</span> <span class="o">**</span><span class="n">ctx</span><span class="p">)</span>
<span class="k">return</span> <span class="n">decorated_function</span>
<span class="k">return</span> <span class="n">decorator</span>
</pre></div>
</div>
</section>
<section id="endpoint-decorator">
<h2>Endpoint Decorator<a class="headerlink" href="#endpoint-decorator" title="Link to this heading"></a></h2>
<p>When you want to use the werkzeug routing system for more flexibility you
need to map the endpoint as defined in the <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/routing/#werkzeug.routing.Rule" title="(in Werkzeug v3.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">Rule</span></code></a>
to a view function. This is possible with this decorator. For example:</p>
<div class="highlight-default 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="kn">from</span><span class="w"> </span><span class="nn">werkzeug.routing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Rule</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="n">app</span><span class="o">.</span><span class="n">url_map</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Rule</span><span class="p">(</span><span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="n">endpoint</span><span class="o">=</span><span class="s1">&#39;index&#39;</span><span class="p">))</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">endpoint</span><span class="p">(</span><span class="s1">&#39;index&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">my_index</span><span class="p">():</span>
<span class="k">return</span> <span class="s2">&quot;Hello world&quot;</span>
</pre></div>
</div>
</section>
</section>
@ -69,20 +218,31 @@
<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="#">View Decorators</a><ul>
<li><a class="reference internal" href="#login-required-decorator">Login Required Decorator</a></li>
<li><a class="reference internal" href="#caching-decorator">Caching Decorator</a></li>
<li><a class="reference internal" href="#templating-decorator">Templating Decorator</a></li>
<li><a class="reference internal" href="#endpoint-decorator">Endpoint Decorator</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="celery.html" title="previous chapter">Background Tasks with Celery</a>
<li>Next: <a href="singlepageapplications.html" title="next chapter">Single-Page Applications</a></ul>
<li>Previous: <a href="caching.html" title="previous chapter">Caching</a>
<li>Next: <a href="wtforms.html" title="next chapter">Form Validation with WTForms</a></ul>
</li>
</ul>
</li>
@ -106,4 +266,4 @@
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

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>

View file

@ -1,174 +1,71 @@
<!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>Using URL Processors &#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="Using SQLite 3 with Flask" href="sqlite3.html" />
<link rel="prev" title="Application Dispatching" href="appdispatch.html" />
<title>Python Module Index &#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" />
</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="#" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="sqlite3.html" title="Using SQLite 3 with Flask"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="appdispatch.html" title="Application Dispatching"
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="">Using URL Processors</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="">Python Module Index</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="using-url-processors">
<h1>Using URL Processors<a class="headerlink" href="#using-url-processors" title="Link to this heading"></a></h1>
<details class="changelog">
<summary>Changelog</summary><div class="versionadded">
<p><span class="versionmodified added">Added in version 0.7.</span></p>
</div>
</details><p>Flask 0.7 introduces the concept of URL processors. The idea is that you
might have a bunch of resources with common parts in the URL that you
dont always explicitly want to provide. For instance you might have a
bunch of URLs that have the language code in it but you dont want to have
to handle it in every single function yourself.</p>
<p>URL processors are especially helpful when combined with blueprints. We
will handle both application specific URL processors here as well as
blueprint specifics.</p>
<section id="internationalized-application-urls">
<h2>Internationalized Application URLs<a class="headerlink" href="#internationalized-application-urls" title="Link to this heading"></a></h2>
<p>Consider an application like this:</p>
<div class="highlight-default 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">g</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;/&lt;lang_code&gt;/&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">(</span><span class="n">lang_code</span><span class="p">):</span>
<span class="n">g</span><span class="o">.</span><span class="n">lang_code</span> <span class="o">=</span> <span class="n">lang_code</span>
<span class="o">...</span>
<h1>Python Module Index</h1>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/&lt;lang_code&gt;/about&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">about</span><span class="p">(</span><span class="n">lang_code</span><span class="p">):</span>
<span class="n">g</span><span class="o">.</span><span class="n">lang_code</span> <span class="o">=</span> <span class="n">lang_code</span>
<span class="o">...</span>
</pre></div>
</div>
<p>This is an awful lot of repetition as you have to handle the language code
setting on the <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> object yourself in every single function.
Sure, a decorator could be used to simplify this, but if you want to
generate URLs from one function to another you would have to still provide
the language code explicitly which can be annoying.</p>
<p>For the latter, this is where <a class="reference internal" href="../api.html#flask.Flask.url_defaults" title="flask.Flask.url_defaults"><code class="xref py py-func docutils literal notranslate"><span class="pre">url_defaults()</span></code></a> functions
come in. They can automatically inject values into a call to
<a class="reference internal" href="../api.html#flask.url_for" title="flask.url_for"><code class="xref py py-func docutils literal notranslate"><span class="pre">url_for()</span></code></a>. The code below checks if the
language code is not yet in the dictionary of URL values and if the
endpoint wants a value named <code class="docutils literal notranslate"><span class="pre">'lang_code'</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@app</span><span class="o">.</span><span class="n">url_defaults</span>
<span class="k">def</span><span class="w"> </span><span class="nf">add_language_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="k">if</span> <span class="s1">&#39;lang_code&#39;</span> <span class="ow">in</span> <span class="n">values</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">g</span><span class="o">.</span><span class="n">lang_code</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">if</span> <span class="n">app</span><span class="o">.</span><span class="n">url_map</span><span class="o">.</span><span class="n">is_endpoint_expecting</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="s1">&#39;lang_code&#39;</span><span class="p">):</span>
<span class="n">values</span><span class="p">[</span><span class="s1">&#39;lang_code&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">g</span><span class="o">.</span><span class="n">lang_code</span>
</pre></div>
</div>
<p>The method <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/routing/#werkzeug.routing.Map.is_endpoint_expecting" title="(in Werkzeug v3.1.x)"><code class="xref py py-meth docutils literal notranslate"><span class="pre">is_endpoint_expecting()</span></code></a> of the URL
map can be used to figure out if it would make sense to provide a language
code for the given endpoint.</p>
<p>The reverse of that function are
<a class="reference internal" href="../api.html#flask.Flask.url_value_preprocessor" title="flask.Flask.url_value_preprocessor"><code class="xref py py-meth docutils literal notranslate"><span class="pre">url_value_preprocessor()</span></code></a>s. They are executed right
after the request was matched and can execute code based on the URL
values. The idea is that they pull information out of the values
dictionary and put it somewhere else:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@app</span><span class="o">.</span><span class="n">url_value_preprocessor</span>
<span class="k">def</span><span class="w"> </span><span class="nf">pull_lang_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="n">g</span><span class="o">.</span><span class="n">lang_code</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;lang_code&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
</pre></div>
</div>
<p>That way you no longer have to do the <code class="code docutils literal notranslate"><span class="pre">lang_code</span></code> assignment to
<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> in every function. You can further improve that by
writing your own decorator that prefixes URLs with the language code, but
the more beautiful solution is using a blueprint. Once the
<code class="docutils literal notranslate"><span class="pre">'lang_code'</span></code> is popped from the values dictionary and it will no longer
be forwarded to the view function reducing the code to this:</p>
<div class="highlight-default 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">g</span>
<div class="modindex-jumpbox">
<a href="#cap-f"><strong>f</strong></a>
</div>
<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">url_defaults</span>
<span class="k">def</span><span class="w"> </span><span class="nf">add_language_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="k">if</span> <span class="s1">&#39;lang_code&#39;</span> <span class="ow">in</span> <span class="n">values</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">g</span><span class="o">.</span><span class="n">lang_code</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">if</span> <span class="n">app</span><span class="o">.</span><span class="n">url_map</span><span class="o">.</span><span class="n">is_endpoint_expecting</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="s1">&#39;lang_code&#39;</span><span class="p">):</span>
<span class="n">values</span><span class="p">[</span><span class="s1">&#39;lang_code&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">g</span><span class="o">.</span><span class="n">lang_code</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">url_value_preprocessor</span>
<span class="k">def</span><span class="w"> </span><span class="nf">pull_lang_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="n">g</span><span class="o">.</span><span class="n">lang_code</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;lang_code&#39;</span><span class="p">,</span> <span class="kc">None</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;/&lt;lang_code&gt;/&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">index</span><span class="p">():</span>
<span class="o">...</span>
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/&lt;lang_code&gt;/about&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">about</span><span class="p">():</span>
<span class="o">...</span>
</pre></div>
</div>
</section>
<section id="internationalized-blueprint-urls">
<h2>Internationalized Blueprint URLs<a class="headerlink" href="#internationalized-blueprint-urls" title="Link to this heading"></a></h2>
<p>Because blueprints can automatically prefix all URLs with a common string
its easy to automatically do that for every function. Furthermore
blueprints can have per-blueprint URL processors which removes a whole lot
of logic from the <a class="reference internal" href="../api.html#flask.Flask.url_defaults" title="flask.Flask.url_defaults"><code class="xref py py-meth docutils literal notranslate"><span class="pre">url_defaults()</span></code></a> function because it no
longer has to check if the URL is really interested in a <code class="docutils literal notranslate"><span class="pre">'lang_code'</span></code>
parameter:</p>
<div class="highlight-default 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">Blueprint</span><span class="p">,</span> <span class="n">g</span>
<span class="n">bp</span> <span class="o">=</span> <span class="n">Blueprint</span><span class="p">(</span><span class="s1">&#39;frontend&#39;</span><span class="p">,</span> <span class="vm">__name__</span><span class="p">,</span> <span class="n">url_prefix</span><span class="o">=</span><span class="s1">&#39;/&lt;lang_code&gt;&#39;</span><span class="p">)</span>
<span class="nd">@bp</span><span class="o">.</span><span class="n">url_defaults</span>
<span class="k">def</span><span class="w"> </span><span class="nf">add_language_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="n">values</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s1">&#39;lang_code&#39;</span><span class="p">,</span> <span class="n">g</span><span class="o">.</span><span class="n">lang_code</span><span class="p">)</span>
<span class="nd">@bp</span><span class="o">.</span><span class="n">url_value_preprocessor</span>
<span class="k">def</span><span class="w"> </span><span class="nf">pull_lang_code</span><span class="p">(</span><span class="n">endpoint</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
<span class="n">g</span><span class="o">.</span><span class="n">lang_code</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s1">&#39;lang_code&#39;</span><span class="p">)</span>
<span class="nd">@bp</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">index</span><span class="p">():</span>
<span class="o">...</span>
<span class="nd">@bp</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/about&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">about</span><span class="p">():</span>
<span class="o">...</span>
</pre></div>
</div>
</section>
</section>
<table class="indextable modindextable">
<tr class="pcap"><td></td><td>&#160;</td><td></td></tr>
<tr class="cap" id="cap-f"><td></td><td>
<strong>f</strong></td><td></td></tr>
<tr>
<td><img src="_static/minus.png" class="toggler"
id="toggle-1" style="display: none" alt="-" /></td>
<td>
<a href="api.html#module-flask"><code class="xref">flask</code></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&#160;&#160;&#160;
<a href="api.html#module-flask.json"><code class="xref">flask.json</code></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&#160;&#160;&#160;
<a href="api.html#module-flask.json.tag"><code class="xref">flask.json.tag</code></a></td><td>
<em></em></td></tr>
</table>
<div class="clearer"></div>
@ -178,37 +75,22 @@ parameter:</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"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Using URL Processors</a><ul>
<li><a class="reference internal" href="#internationalized-application-urls">Internationalized Application URLs</a></li>
<li><a class="reference internal" href="#internationalized-blueprint-urls">Internationalized Blueprint URLs</a></li>
</ul>
</li>
</ul>
<p class="logo"><a href="index.html">
<img class="logo" src="_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Navigation</h3>
<ul>
<li><a href="../index.html">Overview</a>
<ul>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="appdispatch.html" title="previous chapter">Application Dispatching</a>
<li>Next: <a href="sqlite3.html" title="next chapter">Using SQLite 3 with Flask</a></ul>
</li>
</ul>
<li><a href="index.html">Overview</a>
</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>
@ -224,4 +106,4 @@ parameter:</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>

File diff suppressed because it is too large Load diff

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>