flask/flask-docs/lifecycle.html
Edgar Alvarado Taleno 77f3f78332 Preparar para publicar en Read the Docs
Signed-off-by: Edgar Alvarado Taleno <edgar.alvaradotaleno@ucr.ac.cr>
2025-04-10 15:52:02 -06:00

257 lines
No EOL
22 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<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>Application Structure and Lifecycle &#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="The Application Context" href="appcontext.html" />
<link rel="prev" title="Class-based Views" href="views.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"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="appcontext.html" title="The Application Context"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="views.html" title="Class-based 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="">Application Structure and Lifecycle</a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="application-structure-and-lifecycle">
<h1>Application Structure and Lifecycle<a class="headerlink" href="#application-structure-and-lifecycle" title="Link to this heading"></a></h1>
<p>Flask makes it pretty easy to write a web application. But there are quite a few
different parts to an application and to each request it handles. Knowing what happens
during application setup, serving, and handling requests will help you know whats
possible in Flask and how to structure your application.</p>
<section id="application-setup">
<h2>Application Setup<a class="headerlink" href="#application-setup" title="Link to this heading"></a></h2>
<p>The first step in creating a Flask application is creating the application object. Each
Flask application is an instance of 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, which collects all
configuration, extensions, and views.</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="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">SECRET_KEY</span><span class="o">=</span><span class="s2">&quot;dev&quot;</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="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">&quot;/&quot;</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="s2">&quot;Hello, World!&quot;</span>
</pre></div>
</div>
<p>This is known as the “application setup phase”, its the code you write thats outside
any view functions or other handlers. It can be split up between different modules and
sub-packages, but all code that you want to be part of your application must be imported
in order for it to be registered.</p>
<p>All application setup must be completed before you start serving your application and
handling requests. This is because WSGI servers divide work between multiple workers, or
can be distributed across multiple machines. If the configuration changed in one worker,
theres no way for Flask to ensure consistency between other workers.</p>
<p>Flask tries to help developers catch some of these setup ordering issues by showing an
error if setup-related methods are called after requests are handled. In that case
youll see this error:</p>
<blockquote>
<div><p>The setup method route can no longer be called on the application. It has already
handled its first request, any changes will not be applied consistently.
Make sure all imports, decorators, functions, etc. needed to set up the application
are done before running it.</p>
</div></blockquote>
<p>However, it is not possible for Flask to detect all cases of out-of-order setup. In
general, dont do anything to modify the <code class="docutils literal notranslate"><span class="pre">Flask</span></code> app object and <code class="docutils literal notranslate"><span class="pre">Blueprint</span></code> objects
from within view functions that run during requests. This includes:</p>
<ul class="simple">
<li><p>Adding routes, view functions, and other request handlers with <code class="docutils literal notranslate"><span class="pre">&#64;app.route</span></code>,
<code class="docutils literal notranslate"><span class="pre">&#64;app.errorhandler</span></code>, <code class="docutils literal notranslate"><span class="pre">&#64;app.before_request</span></code>, etc.</p></li>
<li><p>Registering blueprints.</p></li>
<li><p>Loading configuration with <code class="docutils literal notranslate"><span class="pre">app.config</span></code>.</p></li>
<li><p>Setting up the Jinja template environment with <code class="docutils literal notranslate"><span class="pre">app.jinja_env</span></code>.</p></li>
<li><p>Setting a session interface, instead of the default itsdangerous cookie.</p></li>
<li><p>Setting a JSON provider with <code class="docutils literal notranslate"><span class="pre">app.json</span></code>, instead of the default provider.</p></li>
<li><p>Creating and initializing Flask extensions.</p></li>
</ul>
</section>
<section id="serving-the-application">
<h2>Serving the Application<a class="headerlink" href="#serving-the-application" title="Link to this heading"></a></h2>
<p>Flask is a WSGI application framework. The other half of WSGI is the WSGI server. During
development, Flask, through Werkzeug, provides a development WSGI server with the
<code class="docutils literal notranslate"><span class="pre">flask</span> <span class="pre">run</span></code> CLI command. When you are done with development, use a production server
to serve your application, see <a class="reference internal" href="deploying/index.html"><span class="doc">Deploying to Production</span></a>.</p>
<p>Regardless of what server youre using, it will follow the <span class="target" id="index-0"></span><a class="pep reference external" href="https://peps.python.org/pep-3333/"><strong>PEP 3333</strong></a> WSGI spec. The
WSGI server will be told how to access your Flask application object, which is the WSGI
application. Then it will start listening for HTTP requests, translate the request data
into a WSGI environ, and call the WSGI application with that data. The WSGI application
will return data that is translated into an HTTP response.</p>
<ol class="arabic simple">
<li><p>Browser or other client makes HTTP request.</p></li>
<li><p>WSGI server receives request.</p></li>
<li><p>WSGI server converts HTTP data to WSGI <code class="docutils literal notranslate"><span class="pre">environ</span></code> dict.</p></li>
<li><p>WSGI server calls WSGI application with the <code class="docutils literal notranslate"><span class="pre">environ</span></code>.</p></li>
<li><p>Flask, the WSGI application, does all its internal processing to route the request
to a view function, handle errors, etc.</p></li>
<li><p>Flask translates View function return into WSGI response data, passes it to WSGI
server.</p></li>
<li><p>WSGI server creates and send an HTTP response.</p></li>
<li><p>Client receives the HTTP response.</p></li>
</ol>
<section id="middleware">
<h3>Middleware<a class="headerlink" href="#middleware" title="Link to this heading"></a></h3>
<p>The WSGI application above is a callable that behaves in a certain way. Middleware
is a WSGI application that wraps another WSGI application. Its a similar concept to
Python decorators. The outermost middleware will be called by the server. It can modify
the data passed to it, then call the WSGI application (or further middleware) that it
wraps, and so on. And it can take the return value of that call and modify it further.</p>
<p>From the WSGI servers perspective, there is one WSGI application, the one it calls
directly. Typically, Flask is the “real” application at the end of the chain of
middleware. But even Flask can call further WSGI applications, although thats an
advanced, uncommon use case.</p>
<p>A common middleware youll see used with Flask is Werkzeugs
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/middleware/proxy_fix/#werkzeug.middleware.proxy_fix.ProxyFix" title="(in Werkzeug v3.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">ProxyFix</span></code></a>, which modifies the request to look
like it came directly from a client even if it passed through HTTP proxies on the way.
There are other middleware that can handle serving static files, authentication, etc.</p>
</section>
</section>
<section id="how-a-request-is-handled">
<h2>How a Request is Handled<a class="headerlink" href="#how-a-request-is-handled" title="Link to this heading"></a></h2>
<p>For us, the interesting part of the steps above is when Flask gets called by the WSGI
server (or middleware). At that point, it will do quite a lot to handle the request and
generate the response. At the most basic, it will match the URL to a view function, call
the view function, and pass the return value back to the server. But there are many more
parts that you can use to customize its behavior.</p>
<ol class="arabic simple">
<li><p>WSGI server calls the Flask object, which calls <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>.</p></li>
<li><p>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> object is created. This converts the WSGI <code class="docutils literal notranslate"><span class="pre">environ</span></code>
dict into 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. It also creates an <code class="xref py py-class docutils literal notranslate"><span class="pre">AppContext</span></code> object.</p></li>
<li><p>The <a class="reference internal" href="appcontext.html"><span class="doc">app context</span></a> is pushed, which makes <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> and
<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> available.</p></li>
<li><p>The <a class="reference internal" href="api.html#flask.appcontext_pushed" title="flask.appcontext_pushed"><code class="xref py py-data docutils literal notranslate"><span class="pre">appcontext_pushed</span></code></a> signal is sent.</p></li>
<li><p>The <a class="reference internal" href="reqcontext.html"><span class="doc">request context</span></a> is pushed, which makes <a class="reference internal" href="api.html#flask.request" title="flask.request"><code class="xref py py-attr 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-class docutils literal notranslate"><span class="pre">session</span></code></a> available.</p></li>
<li><p>The session is opened, loading any existing session data using the apps
<a class="reference internal" href="api.html#flask.Flask.session_interface" title="flask.Flask.session_interface"><code class="xref py py-attr docutils literal notranslate"><span class="pre">session_interface</span></code></a>, an instance of <a class="reference internal" href="api.html#flask.sessions.SessionInterface" title="flask.sessions.SessionInterface"><code class="xref py py-class docutils literal notranslate"><span class="pre">SessionInterface</span></code></a>.</p></li>
<li><p>The URL is matched against the URL rules registered with 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 during application setup. If there is no match, the error - usually a 404,
405, or redirect - is stored to be handled later.</p></li>
<li><p>The <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> signal is sent.</p></li>
<li><p>Any <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> decorated functions are called.</p></li>
<li><p>Any <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> decorated functions are called. If any of
these function returns a value it is treated as the response immediately.</p></li>
<li><p>If the URL didnt match a route a few steps ago, that error is raised now.</p></li>
<li><p>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> decorated view function associated with the matched URL
is called and returns a value to be used as the response.</p></li>
<li><p>If any step so far raised an exception, and there is 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>
decorated function that matches the exception class or HTTP error code, it is
called to handle the error and return a response.</p></li>
<li><p>Whatever returned a response value - a before request function, the view, or an
error handler, that value is converted to a <a class="reference internal" href="api.html#flask.Response" title="flask.Response"><code class="xref py py-class docutils literal notranslate"><span class="pre">Response</span></code></a> object.</p></li>
<li><p>Any <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> decorated functions are called, then cleared.</p></li>
<li><p>Any <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> decorated functions are called, which can modify
the response object.</p></li>
<li><p>The session is saved, persisting any modified session data using the apps
<a class="reference internal" href="api.html#flask.Flask.session_interface" title="flask.Flask.session_interface"><code class="xref py py-attr docutils literal notranslate"><span class="pre">session_interface</span></code></a>.</p></li>
<li><p>The <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> signal is sent.</p></li>
<li><p>If any step so far raised an exception, and it was not handled by an error handler
function, it is handled now. HTTP exceptions are treated as responses with their
corresponding status code, other exceptions are converted to a generic 500 response.
The <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> signal is sent.</p></li>
<li><p>The response objects status, headers, and body are returned to the WSGI server.</p></li>
<li><p>Any <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> decorated functions are called.</p></li>
<li><p>The <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> signal is sent.</p></li>
<li><p>The request context is popped, <a class="reference internal" href="api.html#flask.request" title="flask.request"><code class="xref py py-attr 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-class docutils literal notranslate"><span class="pre">session</span></code></a> are no longer
available.</p></li>
<li><p>Any <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> decorated functions are called.</p></li>
<li><p>The <a class="reference internal" href="api.html#flask.appcontext_tearing_down" title="flask.appcontext_tearing_down"><code class="xref py py-data docutils literal notranslate"><span class="pre">appcontext_tearing_down</span></code></a> signal is sent.</p></li>
<li><p>The app context is popped, <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> and <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> are no longer
available.</p></li>
<li><p>The <a class="reference internal" href="api.html#flask.appcontext_popped" title="flask.appcontext_popped"><code class="xref py py-data docutils literal notranslate"><span class="pre">appcontext_popped</span></code></a> signal is sent.</p></li>
</ol>
<p>There are even more decorators and customization points than this, but that arent part
of every request lifecycle. Theyre more specific to certain things you might use during
a request, such as templates, building URLs, or handling JSON data. See the rest of this
documentation, as well as the <a class="reference internal" href="api.html"><span class="doc">API</span></a> to explore further.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<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 Structure and Lifecycle</a><ul>
<li><a class="reference internal" href="#application-setup">Application Setup</a></li>
<li><a class="reference internal" href="#serving-the-application">Serving the Application</a><ul>
<li><a class="reference internal" href="#middleware">Middleware</a></li>
</ul>
</li>
<li><a class="reference internal" href="#how-a-request-is-handled">How a Request is Handled</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="index.html">Overview</a>
<ul>
<li>Previous: <a href="views.html" title="previous chapter">Class-based Views</a>
<li>Next: <a href="appcontext.html" title="next chapter">The Application Context</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">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>