forked from orbit-oss/flask
Rewrote tutorial to use the g based appcontext object
This commit is contained in:
parent
42cf782ee3
commit
05161d3584
7 changed files with 154 additions and 118 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue