552 lines
No EOL
52 KiB
HTML
552 lines
No EOL
52 KiB
HTML
<!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>Handling Application Errors — 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="Debugging Application Errors" href="debugging.html" />
|
||
<link rel="prev" title="Testing Flask Applications" href="testing.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="debugging.html" title="Debugging Application Errors"
|
||
accesskey="N">next</a> |</li>
|
||
<li class="right" >
|
||
<a href="testing.html" title="Testing Flask Applications"
|
||
accesskey="P">previous</a> |</li>
|
||
<li class="nav-item nav-item-0"><a href="index.html">Flask Documentation (3.2.x)</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">Handling Application Errors</a></li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section id="handling-application-errors">
|
||
<h1>Handling Application Errors<a class="headerlink" href="#handling-application-errors" title="Link to this heading">¶</a></h1>
|
||
<p>Applications fail, servers fail. Sooner or later you will see an exception
|
||
in production. Even if your code is 100% correct, you will still see
|
||
exceptions from time to time. Why? Because everything else involved will
|
||
fail. Here are some situations where perfectly fine code can lead to server
|
||
errors:</p>
|
||
<ul class="simple">
|
||
<li><p>the client terminated the request early and the application was still
|
||
reading from the incoming data</p></li>
|
||
<li><p>the database server was overloaded and could not handle the query</p></li>
|
||
<li><p>a filesystem is full</p></li>
|
||
<li><p>a harddrive crashed</p></li>
|
||
<li><p>a backend server overloaded</p></li>
|
||
<li><p>a programming error in a library you are using</p></li>
|
||
<li><p>network connection of the server to another system failed</p></li>
|
||
</ul>
|
||
<p>And that’s just a small sample of issues you could be facing. So how do we
|
||
deal with that sort of problem? By default if your application runs in
|
||
production mode, and an exception is raised Flask will display a very simple
|
||
page for you and log the exception to the <a class="reference internal" href="api.html#flask.Flask.logger" title="flask.Flask.logger"><code class="xref py py-attr docutils literal notranslate"><span class="pre">logger</span></code></a>.</p>
|
||
<p>But there is more you can do, and we will cover some better setups to deal
|
||
with errors including custom exceptions and 3rd party tools.</p>
|
||
<section id="error-logging-tools">
|
||
<span id="id1"></span><h2>Error Logging Tools<a class="headerlink" href="#error-logging-tools" title="Link to this heading">¶</a></h2>
|
||
<p>Sending error mails, even if just for critical ones, can become
|
||
overwhelming if enough users are hitting the error and log files are
|
||
typically never looked at. This is why we recommend using <a class="reference external" href="https://sentry.io/">Sentry</a> for dealing with application errors. It’s
|
||
available as a source-available project <a class="reference external" href="https://github.com/getsentry/sentry">on GitHub</a> and is also available as a <a class="reference external" href="https://sentry.io/signup/">hosted version</a> which you can try for free. Sentry
|
||
aggregates duplicate errors, captures the full stack trace and local
|
||
variables for debugging, and sends you mails based on new errors or
|
||
frequency thresholds.</p>
|
||
<p>To use Sentry you need to install the <code class="docutils literal notranslate"><span class="pre">sentry-sdk</span></code> client with extra
|
||
<code class="docutils literal notranslate"><span class="pre">flask</span></code> dependencies.</p>
|
||
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>$ pip install sentry-sdk[flask]
|
||
</pre></div>
|
||
</div>
|
||
<p>And then add this to your Flask app:</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">sentry_sdk</span>
|
||
<span class="kn">from</span><span class="w"> </span><span class="nn">sentry_sdk.integrations.flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">FlaskIntegration</span>
|
||
|
||
<span class="n">sentry_sdk</span><span class="o">.</span><span class="n">init</span><span class="p">(</span><span class="s1">'YOUR_DSN_HERE'</span><span class="p">,</span> <span class="n">integrations</span><span class="o">=</span><span class="p">[</span><span class="n">FlaskIntegration</span><span class="p">()])</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The <code class="docutils literal notranslate"><span class="pre">YOUR_DSN_HERE</span></code> value needs to be replaced with the DSN value you
|
||
get from your Sentry installation.</p>
|
||
<p>After installation, failures leading to an Internal Server Error
|
||
are automatically reported to Sentry and from there you can
|
||
receive error notifications.</p>
|
||
<p>See also:</p>
|
||
<ul class="simple">
|
||
<li><p>Sentry also supports catching errors from a worker queue
|
||
(RQ, Celery, etc.) in a similar fashion. See the <a class="reference external" href="https://docs.sentry.io/platforms/python/">Python SDK docs</a> for more information.</p></li>
|
||
<li><p><a class="reference external" href="https://docs.sentry.io/platforms/python/guides/flask/">Flask-specific documentation</a></p></li>
|
||
</ul>
|
||
</section>
|
||
<section id="error-handlers">
|
||
<h2>Error Handlers<a class="headerlink" href="#error-handlers" title="Link to this heading">¶</a></h2>
|
||
<p>When an error occurs in Flask, an appropriate <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status">HTTP status code</a> will be
|
||
returned. 400-499 indicate errors with the client’s request data, or
|
||
about the data requested. 500-599 indicate errors with the server or
|
||
application itself.</p>
|
||
<p>You might want to show custom error pages to the user when an error occurs.
|
||
This can be done by registering error handlers.</p>
|
||
<p>An error handler is a function that returns a response when a type of error is
|
||
raised, similar to how a view is a function that returns a response when a
|
||
request URL is matched. It is passed the instance of the error being handled,
|
||
which is most likely a <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPException</span></code></a>.</p>
|
||
<p>The status code of the response will not be set to the handler’s code. Make
|
||
sure to provide the appropriate HTTP status code when returning a response from
|
||
a handler.</p>
|
||
<section id="registering">
|
||
<h3>Registering<a class="headerlink" href="#registering" title="Link to this heading">¶</a></h3>
|
||
<p>Register handlers by decorating a function with
|
||
<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>. Or use
|
||
<a class="reference internal" href="api.html#flask.Flask.register_error_handler" title="flask.Flask.register_error_handler"><code class="xref py py-meth docutils literal notranslate"><span class="pre">register_error_handler()</span></code></a> to register the function later.
|
||
Remember to set the error code when returning the response.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="n">werkzeug</span><span class="o">.</span><span class="n">exceptions</span><span class="o">.</span><span class="n">BadRequest</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">handle_bad_request</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="s1">'bad request!'</span><span class="p">,</span> <span class="mi">400</span>
|
||
|
||
<span class="c1"># or, without the decorator</span>
|
||
<span class="n">app</span><span class="o">.</span><span class="n">register_error_handler</span><span class="p">(</span><span class="mi">400</span><span class="p">,</span> <span class="n">handle_bad_request</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p><a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">werkzeug.exceptions.HTTPException</span></code></a> subclasses like
|
||
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.BadRequest" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">BadRequest</span></code></a> and their HTTP codes are interchangeable
|
||
when registering handlers. (<code class="docutils literal notranslate"><span class="pre">BadRequest.code</span> <span class="pre">==</span> <span class="pre">400</span></code>)</p>
|
||
<p>Non-standard HTTP codes cannot be registered by code because they are not known
|
||
by Werkzeug. Instead, define a subclass of
|
||
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">HTTPException</span></code></a> with the appropriate code and
|
||
register and raise that exception class.</p>
|
||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">InsufficientStorage</span><span class="p">(</span><span class="n">werkzeug</span><span class="o">.</span><span class="n">exceptions</span><span class="o">.</span><span class="n">HTTPException</span><span class="p">):</span>
|
||
<span class="n">code</span> <span class="o">=</span> <span class="mi">507</span>
|
||
<span class="n">description</span> <span class="o">=</span> <span class="s1">'Not enough storage space.'</span>
|
||
|
||
<span class="n">app</span><span class="o">.</span><span class="n">register_error_handler</span><span class="p">(</span><span class="n">InsufficientStorage</span><span class="p">,</span> <span class="n">handle_507</span><span class="p">)</span>
|
||
|
||
<span class="k">raise</span> <span class="n">InsufficientStorage</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Handlers can be registered for any exception class, not just
|
||
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPException</span></code></a> subclasses or HTTP status
|
||
codes. Handlers can be registered for a specific class, or for all subclasses
|
||
of a parent class.</p>
|
||
</section>
|
||
<section id="handling">
|
||
<h3>Handling<a class="headerlink" href="#handling" title="Link to this heading">¶</a></h3>
|
||
<p>When building a Flask application you <em>will</em> run into exceptions. If some part
|
||
of your code breaks while handling a request (and you have no error handlers
|
||
registered), a “500 Internal Server Error”
|
||
(<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.InternalServerError" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">InternalServerError</span></code></a>) will be returned by default.
|
||
Similarly, “404 Not Found”
|
||
(<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.NotFound" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">NotFound</span></code></a>) error will occur if a request is sent to an unregistered route.
|
||
If a route receives an unallowed request method, a “405 Method Not Allowed”
|
||
(<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.MethodNotAllowed" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">MethodNotAllowed</span></code></a>) will be raised. These are all
|
||
subclasses of <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">HTTPException</span></code></a> and are provided by
|
||
default in Flask.</p>
|
||
<p>Flask gives you the ability to raise any HTTP exception registered by
|
||
Werkzeug. However, the default HTTP exceptions return simple exception
|
||
pages. You might want to show custom error pages to the user when an error occurs.
|
||
This can be done by registering error handlers.</p>
|
||
<p>When Flask catches an exception while handling a request, it is first looked up by code.
|
||
If no handler is registered for the code, Flask looks up the error by its class hierarchy; the most specific handler is chosen.
|
||
If no handler is registered, <a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-class docutils literal notranslate"><span class="pre">HTTPException</span></code></a> subclasses show a
|
||
generic message about their code, while other exceptions are converted to a
|
||
generic “500 Internal Server Error”.</p>
|
||
<p>For example, if an instance of <a class="reference external" href="https://docs.python.org/3/library/exceptions.html#ConnectionRefusedError" title="(in Python v3.13)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ConnectionRefusedError</span></code></a> is raised,
|
||
and a handler is registered for <a class="reference external" href="https://docs.python.org/3/library/exceptions.html#ConnectionError" title="(in Python v3.13)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ConnectionError</span></code></a> and
|
||
<a class="reference external" href="https://docs.python.org/3/library/exceptions.html#ConnectionRefusedError" title="(in Python v3.13)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ConnectionRefusedError</span></code></a>, the more specific <a class="reference external" href="https://docs.python.org/3/library/exceptions.html#ConnectionRefusedError" title="(in Python v3.13)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ConnectionRefusedError</span></code></a>
|
||
handler is called with the exception instance to generate the response.</p>
|
||
<p>Handlers registered on the blueprint take precedence over those registered
|
||
globally on the application, assuming a blueprint is handling the request that
|
||
raises the exception. However, the blueprint cannot handle 404 routing errors
|
||
because the 404 occurs at the routing level before the blueprint can be
|
||
determined.</p>
|
||
</section>
|
||
<section id="generic-exception-handlers">
|
||
<h3>Generic Exception Handlers<a class="headerlink" href="#generic-exception-handlers" title="Link to this heading">¶</a></h3>
|
||
<p>It is possible to register error handlers for very generic base classes
|
||
such as <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> or even <code class="docutils literal notranslate"><span class="pre">Exception</span></code>. However, be aware that
|
||
these will catch more than you might expect.</p>
|
||
<p>For example, an error handler for <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> might be useful for turning
|
||
the default HTML errors pages into JSON. However, this
|
||
handler will trigger for things you don’t cause directly, such as 404
|
||
and 405 errors during routing. Be sure to craft your handler carefully
|
||
so you don’t lose information about the HTTP error.</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">json</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">HTTPException</span>
|
||
|
||
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="n">HTTPException</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">handle_exception</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""Return JSON instead of HTML for HTTP errors."""</span>
|
||
<span class="c1"># start with the correct headers and status code from the error</span>
|
||
<span class="n">response</span> <span class="o">=</span> <span class="n">e</span><span class="o">.</span><span class="n">get_response</span><span class="p">()</span>
|
||
<span class="c1"># replace the body with JSON</span>
|
||
<span class="n">response</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">({</span>
|
||
<span class="s2">"code"</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">code</span><span class="p">,</span>
|
||
<span class="s2">"name"</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
|
||
<span class="s2">"description"</span><span class="p">:</span> <span class="n">e</span><span class="o">.</span><span class="n">description</span><span class="p">,</span>
|
||
<span class="p">})</span>
|
||
<span class="n">response</span><span class="o">.</span><span class="n">content_type</span> <span class="o">=</span> <span class="s2">"application/json"</span>
|
||
<span class="k">return</span> <span class="n">response</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>An error handler for <code class="docutils literal notranslate"><span class="pre">Exception</span></code> might seem useful for changing how
|
||
all errors, even unhandled ones, are presented to the user. However,
|
||
this is similar to doing <code class="docutils literal notranslate"><span class="pre">except</span> <span class="pre">Exception:</span></code> in Python, it will
|
||
capture <em>all</em> otherwise unhandled errors, including all HTTP status
|
||
codes.</p>
|
||
<p>In most cases it will be safer to register handlers for more
|
||
specific exceptions. Since <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> instances are valid WSGI
|
||
responses, you could also pass them through directly.</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.exceptions</span><span class="w"> </span><span class="kn">import</span> <span class="n">HTTPException</span>
|
||
|
||
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="ne">Exception</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">handle_exception</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="c1"># pass through HTTP errors</span>
|
||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">HTTPException</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">e</span>
|
||
|
||
<span class="c1"># now you're handling non-HTTP exceptions only</span>
|
||
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">"500_generic.html"</span><span class="p">,</span> <span class="n">e</span><span class="o">=</span><span class="n">e</span><span class="p">),</span> <span class="mi">500</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Error handlers still respect the exception class hierarchy. If you
|
||
register handlers for both <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> and <code class="docutils literal notranslate"><span class="pre">Exception</span></code>, the
|
||
<code class="docutils literal notranslate"><span class="pre">Exception</span></code> handler will not handle <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> subclasses
|
||
because the <code class="docutils literal notranslate"><span class="pre">HTTPException</span></code> handler is more specific.</p>
|
||
</section>
|
||
<section id="unhandled-exceptions">
|
||
<h3>Unhandled Exceptions<a class="headerlink" href="#unhandled-exceptions" title="Link to this heading">¶</a></h3>
|
||
<p>When there is no error handler registered for an exception, a 500
|
||
Internal Server Error will be returned instead. See
|
||
<a class="reference internal" href="api.html#flask.Flask.handle_exception" title="flask.Flask.handle_exception"><code class="xref py py-meth docutils literal notranslate"><span class="pre">flask.Flask.handle_exception()</span></code></a> for information about this
|
||
behavior.</p>
|
||
<p>If there is an error handler registered for <code class="docutils literal notranslate"><span class="pre">InternalServerError</span></code>,
|
||
this will be invoked. As of Flask 1.1.0, this error handler will always
|
||
be passed an instance of <code class="docutils literal notranslate"><span class="pre">InternalServerError</span></code>, not the original
|
||
unhandled error.</p>
|
||
<p>The original error is available as <code class="docutils literal notranslate"><span class="pre">e.original_exception</span></code>.</p>
|
||
<p>An error handler for “500 Internal Server Error” will be passed uncaught
|
||
exceptions in addition to explicit 500 errors. In debug mode, a handler
|
||
for “500 Internal Server Error” will not be used. Instead, the
|
||
interactive debugger will be shown.</p>
|
||
</section>
|
||
</section>
|
||
<section id="custom-error-pages">
|
||
<h2>Custom Error Pages<a class="headerlink" href="#custom-error-pages" title="Link to this heading">¶</a></h2>
|
||
<p>Sometimes when building a Flask application, you might want to raise a
|
||
<a class="reference external" href="https://werkzeug.palletsprojects.com/en/stable/exceptions/#werkzeug.exceptions.HTTPException" title="(in Werkzeug v3.1.x)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPException</span></code></a> to signal to the user that
|
||
something is wrong with the request. Fortunately, Flask comes with a handy
|
||
<a class="reference internal" href="api.html#flask.abort" title="flask.abort"><code class="xref py py-func docutils literal notranslate"><span class="pre">abort()</span></code></a> function that aborts a request with a HTTP error from
|
||
werkzeug as desired. It will also provide a plain black and white error page
|
||
for you with a basic description, but nothing fancy.</p>
|
||
<p>Depending on the error code it is less or more likely for the user to
|
||
actually see such an error.</p>
|
||
<p>Consider the code below, we might have a user profile route, and if the user
|
||
fails to pass a username we can raise a “400 Bad Request”. If the user passes a
|
||
username and we can’t find it, we raise a “404 Not Found”.</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">abort</span><span class="p">,</span> <span class="n">render_template</span><span class="p">,</span> <span class="n">request</span>
|
||
|
||
<span class="c1"># a username needs to be supplied in the query args</span>
|
||
<span class="c1"># a successful request would be like /profile?username=jack</span>
|
||
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">"/profile"</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">user_profile</span><span class="p">():</span>
|
||
<span class="n">username</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">arg</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"username"</span><span class="p">)</span>
|
||
<span class="c1"># if a username isn't supplied in the request, return a 400 bad request</span>
|
||
<span class="k">if</span> <span class="n">username</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="n">abort</span><span class="p">(</span><span class="mi">400</span><span class="p">)</span>
|
||
|
||
<span class="n">user</span> <span class="o">=</span> <span class="n">get_user</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="n">username</span><span class="p">)</span>
|
||
<span class="c1"># if a user can't be found by their username, return 404 not found</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="n">abort</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">"profile.html"</span><span class="p">,</span> <span class="n">user</span><span class="o">=</span><span class="n">user</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>Here is another example implementation for a “404 Page Not Found” exception:</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">render_template</span>
|
||
|
||
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">page_not_found</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="c1"># note that we set the 404 status explicitly</span>
|
||
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">'404.html'</span><span class="p">),</span> <span class="mi">404</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>When using <a class="reference internal" href="patterns/appfactories.html"><span class="doc">Application Factories</span></a>:</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">render_template</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">page_not_found</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">'404.html'</span><span class="p">),</span> <span class="mi">404</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">register_error_handler</span><span class="p">(</span><span class="mi">404</span><span class="p">,</span> <span class="n">page_not_found</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">app</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>An example template might be 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">"layout.html"</span> <span class="cp">%}</span>
|
||
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">title</span> <span class="cp">%}</span>Page Not Found<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">body</span> <span class="cp">%}</span>
|
||
<span class="p"><</span><span class="nt">h1</span><span class="p">></span>Page Not Found<span class="p"></</span><span class="nt">h1</span><span class="p">></span>
|
||
<span class="p"><</span><span class="nt">p</span><span class="p">></span>What you were looking for is just not there.
|
||
<span class="p"><</span><span class="nt">p</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">url_for</span><span class="o">(</span><span class="s1">'index'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span>go somewhere nice<span class="p"></</span><span class="nt">a</span><span class="p">></span>
|
||
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
|
||
</pre></div>
|
||
</div>
|
||
<section id="further-examples">
|
||
<h3>Further Examples<a class="headerlink" href="#further-examples" title="Link to this heading">¶</a></h3>
|
||
<p>The above examples wouldn’t actually be an improvement on the default
|
||
exception pages. We can create a custom 500.html template 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">"layout.html"</span> <span class="cp">%}</span>
|
||
<span class="cp">{%</span> <span class="k">block</span> <span class="nv">title</span> <span class="cp">%}</span>Internal Server Error<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">body</span> <span class="cp">%}</span>
|
||
<span class="p"><</span><span class="nt">h1</span><span class="p">></span>Internal Server Error<span class="p"></</span><span class="nt">h1</span><span class="p">></span>
|
||
<span class="p"><</span><span class="nt">p</span><span class="p">></span>Oops... we seem to have made a mistake, sorry!<span class="p"></</span><span class="nt">p</span><span class="p">></span>
|
||
<span class="p"><</span><span class="nt">p</span><span class="p">><</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">"</span><span class="cp">{{</span> <span class="nv">url_for</span><span class="o">(</span><span class="s1">'index'</span><span class="o">)</span> <span class="cp">}}</span><span class="s">"</span><span class="p">></span>Go somewhere nice instead<span class="p"></</span><span class="nt">a</span><span class="p">></span>
|
||
<span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>It can be implemented by rendering the template on “500 Internal Server Error”:</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">render_template</span>
|
||
|
||
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">internal_server_error</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="c1"># note that we set the 500 status explicitly</span>
|
||
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">'500.html'</span><span class="p">),</span> <span class="mi">500</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>When using <a class="reference internal" href="patterns/appfactories.html"><span class="doc">Application Factories</span></a>:</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">render_template</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">internal_server_error</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">'500.html'</span><span class="p">),</span> <span class="mi">500</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">create_app</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">register_error_handler</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="n">internal_server_error</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">app</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>When using <a class="reference internal" href="blueprints.html"><span class="doc">Modular Applications with Blueprints</span></a>:</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">Blueprint</span>
|
||
|
||
<span class="n">blog</span> <span class="o">=</span> <span class="n">Blueprint</span><span class="p">(</span><span class="s1">'blog'</span><span class="p">,</span> <span class="vm">__name__</span><span class="p">)</span>
|
||
|
||
<span class="c1"># as a decorator</span>
|
||
<span class="nd">@blog</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">internal_server_error</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s1">'500.html'</span><span class="p">),</span> <span class="mi">500</span>
|
||
|
||
<span class="c1"># or with register_error_handler</span>
|
||
<span class="n">blog</span><span class="o">.</span><span class="n">register_error_handler</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="n">internal_server_error</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</section>
|
||
<section id="blueprint-error-handlers">
|
||
<h2>Blueprint Error Handlers<a class="headerlink" href="#blueprint-error-handlers" title="Link to this heading">¶</a></h2>
|
||
<p>In <a class="reference internal" href="blueprints.html"><span class="doc">Modular Applications with Blueprints</span></a>, most error handlers will work as expected.
|
||
However, there is a caveat concerning handlers for 404 and 405
|
||
exceptions. These error handlers are only invoked from an appropriate
|
||
<code class="docutils literal notranslate"><span class="pre">raise</span></code> statement or a call to <code class="docutils literal notranslate"><span class="pre">abort</span></code> in another of the blueprint’s
|
||
view functions; they are not invoked by, e.g., an invalid URL access.</p>
|
||
<p>This is because the blueprint does not “own” a certain URL space, so
|
||
the application instance has no way of knowing which blueprint error
|
||
handler it should run if given an invalid URL. If you would like to
|
||
execute different handling strategies for these errors based on URL
|
||
prefixes, they may be defined at the application level using the
|
||
<code class="docutils literal notranslate"><span class="pre">request</span></code> proxy object.</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="p">,</span> <span class="n">render_template</span>
|
||
|
||
<span class="c1"># at the application level</span>
|
||
<span class="c1"># not the blueprint level</span>
|
||
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">page_not_found</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="c1"># if a request is in our blog URL space</span>
|
||
<span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">'/blog/'</span><span class="p">):</span>
|
||
<span class="c1"># we return a custom blog 404 page</span>
|
||
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">"blog/404.html"</span><span class="p">),</span> <span class="mi">404</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># otherwise we return our generic site-wide 404 page</span>
|
||
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">"404.html"</span><span class="p">),</span> <span class="mi">404</span>
|
||
|
||
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">405</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">method_not_allowed</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="c1"># if a request has the wrong method to our API</span>
|
||
<span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">'/api/'</span><span class="p">):</span>
|
||
<span class="c1"># we return a json saying so</span>
|
||
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">message</span><span class="o">=</span><span class="s2">"Method Not Allowed"</span><span class="p">),</span> <span class="mi">405</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># otherwise we return a generic site-wide 405 page</span>
|
||
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s2">"405.html"</span><span class="p">),</span> <span class="mi">405</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="returning-api-errors-as-json">
|
||
<h2>Returning API Errors as JSON<a class="headerlink" href="#returning-api-errors-as-json" title="Link to this heading">¶</a></h2>
|
||
<p>When building APIs in Flask, some developers realise that the built-in
|
||
exceptions are not expressive enough for APIs and that the content type of
|
||
<em class="mimetype">text/html</em> they are emitting is not very useful for API consumers.</p>
|
||
<p>Using the same techniques as above and <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> we can return JSON
|
||
responses to API errors. <a class="reference internal" href="api.html#flask.abort" title="flask.abort"><code class="xref py py-func docutils literal notranslate"><span class="pre">abort()</span></code></a> is called
|
||
with a <code class="docutils literal notranslate"><span class="pre">description</span></code> parameter. The error handler will
|
||
use that as the JSON error message, and set the status code to 404.</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">abort</span><span class="p">,</span> <span class="n">jsonify</span>
|
||
|
||
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">resource_not_found</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">error</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)),</span> <span class="mi">404</span>
|
||
|
||
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">"/cheese"</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">get_one_cheese</span><span class="p">():</span>
|
||
<span class="n">resource</span> <span class="o">=</span> <span class="n">get_resource</span><span class="p">()</span>
|
||
|
||
<span class="k">if</span> <span class="n">resource</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="n">abort</span><span class="p">(</span><span class="mi">404</span><span class="p">,</span> <span class="n">description</span><span class="o">=</span><span class="s2">"Resource not found"</span><span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">resource</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>We can also create custom exception classes. For instance, we can
|
||
introduce a new custom exception for an API that can take a proper human readable message,
|
||
a status code for the error and some optional payload to give more context
|
||
for the error.</p>
|
||
<p>This is a simple example:</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="p">,</span> <span class="n">request</span>
|
||
|
||
<span class="k">class</span><span class="w"> </span><span class="nc">InvalidAPIUsage</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
||
<span class="n">status_code</span> <span class="o">=</span> <span class="mi">400</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">message</span><span class="p">,</span> <span class="n">status_code</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">payload</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">message</span> <span class="o">=</span> <span class="n">message</span>
|
||
<span class="k">if</span> <span class="n">status_code</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">status_code</span> <span class="o">=</span> <span class="n">status_code</span>
|
||
<span class="bp">self</span><span class="o">.</span><span class="n">payload</span> <span class="o">=</span> <span class="n">payload</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">to_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||
<span class="n">rv</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">payload</span> <span class="ow">or</span> <span class="p">())</span>
|
||
<span class="n">rv</span><span class="p">[</span><span class="s1">'message'</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">message</span>
|
||
<span class="k">return</span> <span class="n">rv</span>
|
||
|
||
<span class="nd">@app</span><span class="o">.</span><span class="n">errorhandler</span><span class="p">(</span><span class="n">InvalidAPIUsage</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">invalid_api_usage</span><span class="p">(</span><span class="n">e</span><span class="p">):</span>
|
||
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">to_dict</span><span class="p">()),</span> <span class="n">e</span><span class="o">.</span><span class="n">status_code</span>
|
||
|
||
<span class="c1"># an API app route for getting user information</span>
|
||
<span class="c1"># a correct request might be /api/user?user_id=420</span>
|
||
<span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">"/api/user"</span><span class="p">)</span>
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">user_api</span><span class="p">(</span><span class="n">user_id</span><span class="p">):</span>
|
||
<span class="n">user_id</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">arg</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"user_id"</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">user_id</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="n">InvalidAPIUsage</span><span class="p">(</span><span class="s2">"No user id provided!"</span><span class="p">)</span>
|
||
|
||
<span class="n">user</span> <span class="o">=</span> <span class="n">get_user</span><span class="p">(</span><span class="n">user_id</span><span class="o">=</span><span class="n">user_id</span><span class="p">)</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">user</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="n">InvalidAPIUsage</span><span class="p">(</span><span class="s2">"No such user!"</span><span class="p">,</span> <span class="n">status_code</span><span class="o">=</span><span class="mi">404</span><span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">user</span><span class="o">.</span><span class="n">to_dict</span><span class="p">())</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>A view can now raise that exception with an error message. Additionally
|
||
some extra payload can be provided as a dictionary through the <code class="code docutils literal notranslate"><span class="pre">payload</span></code>
|
||
parameter.</p>
|
||
</section>
|
||
<section id="logging">
|
||
<h2>Logging<a class="headerlink" href="#logging" title="Link to this heading">¶</a></h2>
|
||
<p>See <a class="reference internal" href="logging.html"><span class="doc">Logging</span></a> for information about how to log exceptions, such as
|
||
by emailing them to admins.</p>
|
||
</section>
|
||
<section id="debugging">
|
||
<h2>Debugging<a class="headerlink" href="#debugging" title="Link to this heading">¶</a></h2>
|
||
<p>See <a class="reference internal" href="debugging.html"><span class="doc">Debugging Application Errors</span></a> for information about how to debug errors in
|
||
development and production.</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="#">Handling Application Errors</a><ul>
|
||
<li><a class="reference internal" href="#error-logging-tools">Error Logging Tools</a></li>
|
||
<li><a class="reference internal" href="#error-handlers">Error Handlers</a><ul>
|
||
<li><a class="reference internal" href="#registering">Registering</a></li>
|
||
<li><a class="reference internal" href="#handling">Handling</a></li>
|
||
<li><a class="reference internal" href="#generic-exception-handlers">Generic Exception Handlers</a></li>
|
||
<li><a class="reference internal" href="#unhandled-exceptions">Unhandled Exceptions</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#custom-error-pages">Custom Error Pages</a><ul>
|
||
<li><a class="reference internal" href="#further-examples">Further Examples</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#blueprint-error-handlers">Blueprint Error Handlers</a></li>
|
||
<li><a class="reference internal" href="#returning-api-errors-as-json">Returning API Errors as JSON</a></li>
|
||
<li><a class="reference internal" href="#logging">Logging</a></li>
|
||
<li><a class="reference internal" href="#debugging">Debugging</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li><a href="index.html">Overview</a>
|
||
<ul>
|
||
<li>Previous: <a href="testing.html" title="previous chapter">Testing Flask Applications</a>
|
||
<li>Next: <a href="debugging.html" title="next chapter">Debugging Application Errors</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">
|
||
© Copyright 2010 Pallets.
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
|
||
</div>
|
||
</body>
|
||
</html> |