Rewrote tutorial to use the g based appcontext object

This commit is contained in:
Armin Ronacher 2013-09-01 01:32:41 +06:00
parent 42cf782ee3
commit 05161d3584
7 changed files with 154 additions and 118 deletions

View file

@ -1,56 +1,72 @@
.. _tutorial-dbcon:
Step 4: Request Database Connections
------------------------------------
Step 3: Database Connections
----------------------------
Now we know how we can open database connections and use them for scripts,
but how can we elegantly do that for requests? We will need the database
connection in all our functions so it makes sense to initialize them
before each request and shut them down afterwards.
We have created a function for establishing a database connection with
`create_db` but by itself that's not particularly useful. Creating and
closing database connections all the time is very inefficient, so we want
to keep it around for longer. Because database connections encapsulate a
transaction we also need to make sure that only one request at the time
uses the connection. So how can we elegantly do that with Flask?
Flask allows us to do that with the :meth:`~flask.Flask.before_request`,
:meth:`~flask.Flask.after_request` and :meth:`~flask.Flask.teardown_request`
decorators::
This is where the application context comes into play. So let's start
there.
@app.before_request
def before_request():
g.db = connect_db()
Flask provides us with two contexts: the application context and the
request context. For the time being all you have to know is that there
are special variables that use these. For instance the
:data:`~flask.request` variable is the request object associated with
the current request, whereas :data:`~flask.g` is a general purpose
variable associated with the current application context. We will go into
the details of this a bit later.
@app.teardown_request
def teardown_request(exception):
db = getattr(g, 'db', None)
if db is not None:
db.close()
For the time being all you have to know is that you can store information
savely on the :data:`~flask.g` object.
Functions marked with :meth:`~flask.Flask.before_request` are called before
a request and passed no arguments. Functions marked with
:meth:`~flask.Flask.after_request` are called after a request and
passed the response that will be sent to the client. They have to return
that response object or a different one. They are however not guaranteed
to be executed if an exception is raised, this is where functions marked with
:meth:`~flask.Flask.teardown_request` come in. They get called after the
response has been constructed. They are not allowed to modify the request, and
their return values are ignored. If an exception occurred while the request was
being processed, it is passed to each function; otherwise, `None` is passed in.
So when do you put it on there? To do that you can make a helper
function. The first time the function is called it will create a database
connection for the current context and successive calls will return the
already established connection::
We store our current database connection on the special :data:`~flask.g`
object that Flask provides for us. This object stores information for one
request only and is available from within each function. Never store such
things on other objects because this would not work with threaded
environments. That special :data:`~flask.g` object does some magic behind
the scenes to ensure it does the right thing.
def get_db():
"""Opens a new database connection if there is none yet for the
current application context.
"""
if not hasattr(g, 'sqlite_db'):
g.sqlite_db = connect_db()
return g.sqlite_db
For an even better way to handle such resources see the :ref:`sqlite3`
documentation.
Continue to :ref:`tutorial-views`.
So now we know how to connect, but how do we properly disconnect? For
that flask provides us with the :meth:`~flask.Flask.teardown_appcontext`
decorator. It's executed every time the application context tears down::
@app.teardown_appcontext
def close_db(error):
"""Closes the database again at the end of the request."""
if hasattr(g, 'sqlite_db'):
g.sqlite_db.close()
Functions marked with :meth:`~flask.Flask.teardown_appcontext` are called
every time the app context tears down. So what does this mean?
Essentially the app context is created before the request comes in and is
destroyed (teared down) whenever the request finishes. A teardown can
happen because of two reasons: either everything went well (the error
parameter will be `None`) or an exception happend in which case the error
is passed to the teardown function.
Curious about what these contexts mean? Have a look at the
:ref:`app-context` documentation to learn more.
Continue to :ref:`tutorial-dbinit`.
.. hint:: Where do I put this code?
If you've been following along in this tutorial, you might be wondering
where to put the code from this step and the next. A logical place is to
group these module-level functions together, and put your new
``before_request`` and ``teardown_request`` functions below your existing
``get_db`` and ``close_db`` functions below your existing
``init_db`` function (following the tutorial line-by-line).
If you need a moment to find your bearings, take a look at how the `example