Ep. 26 Flask before and after request
10 Apr 2019
Flask before and after request functions | Learning Flask Ep. 26
In this short article, we're going to be taking a look at some of the ways we can run functions before and after a request in Flask, using the before_request
and after_request
decorators and a few others.
We'll start out with a very basic Flask application:
before_request
The before_request
decorator allows us to create a function that will run before each request.
We can use it by decorating a function with @app.before_request
:
Adding this function to our application and making a request to the route /
, we get the following output in the terminal:
before_request
functions are ideal for tasks such as:
Opening database connections
Loading a user from the session
Working with the flask g object
Functions decorated with before_request
are not required to return anything, however - If a before_request
function returns a non None
value, it will be handled as if it was the return value for the view and any further request handling is stopped.
For example:
If you were to make any requests or go to any route in your application, you'd see Intercepted by before_request
as the return value.
Let's import session
and g
and work with them in the before_request
function:
To work with the session
object, we'll need to assign a secret_key
to our app:
For the sake of this example, we'll just assign a key & value to the session
object and set an attribute username
on the g
object.
You would typically use a function like this to:
Get a unique user ID from the session
Fetch the user from a database
Assign the user to the g object
Here's the example:
Running the app and accessing our route gives us the same output as before, so let's access these values from our route:
Running the app and accessing our route, we see the following output in the terminal:
We're able to access session["foo"]
and g.username
which we set in before_request
as it's available in the context of the request.
before_first_request
Functions decorated with @app.before_first_request
will run once before the first request to this instance of the application:
Running the app and making a couple of requests, we see the following output:
As you'll notice, the before_first_request
fucntion only ran once before the very first request to the app and is ignored on subsequent requests.
Depending on your application, you may want to use a before_first_request
function to do some database maintenance or any other task that only needs to happen once.
after_request
Functions decorated with after_request
work in the same way as before_request
, except they are run after each request.
An important thing to note is that any after_request
functions must take and return an instance of the Flask response class.
Here's a simple example:
Running our app and making a request to our route, we see:
after_request
functions will be run after every request and provide access to the request context, meaning we still have access to ssession
and g
. For example:
At this point you might be thinking; This is a great place to do something like close a database connection, and you'd be right.
However something to note is that any functions decorated with after_request
will NOT run if your application throws an exception.
We can illustrate this by raising an exception in our route:
Running our app and accessing our route, we see:
As expected, both our before_first_request
and before_request
functions ran, however raising the ValueError
in our route brought our application to a halt and after_request
didn't run.
Fortunately, we can get around this with teardown_request
.
teardown_request
Functions decorated with teardown_request
behave similarly to after_request
functions, however, they have the added benefit of being triggered regardless of any exceptions raised.
This makes teardown_request
functions a great place to do any cleanup operations after requests, as we know these function will always run.
Note - In debug mode, Flask will not tear down a request on exception immidiately.
From the Flask docs:
"Generally teardown functions must take every necessary step to avoid that they will fail. If they do execute code that might fail they will have to surround the execution of these code by try/except statements and log occurring errors."
When a teardown function was called because of an exception it will be passed an error object.
Due to the nature of how Flask handles teardown_request
in debug mode, we'll run export FLASK_ENV=production
to see our function in action.
Running our app without raising the ValueError
in our route, we see:
We can see that teardown_request
ran as expected as it will run regardless of whether an exception was raised or not.
Running our app and raising the ValueError
in our route, we see:
Digging through the debug message in the console, we see that teardown_request
has run and the message raised in the exception has been passed to it and printed, whereas after_request
was not triggered.
All together
Putting everything together, our application looks like this:
Wrapping up
Using some of Flasks built in decorators allows us to add another layer of functionality and validation to our applications and should be taken advantage of!
We've only provided a few examples here, and you'll find other useful functions for working with requests, both before and after over at the link to the Flask API documentation below:
Last modified · 10 Apr 2019 Reference : https://pythonise.com/series/learning-flask/python-before-after-request#related
Last updated