forked from orbit-oss/flask
Merge pull request #1277 from iKevinY/doc-fixes
Documentation fixes (mostly in Tutorial)
This commit is contained in:
commit
82d7c49d00
15 changed files with 101 additions and 99 deletions
2
docs/_templates/sidebarintro.html
vendored
2
docs/_templates/sidebarintro.html
vendored
|
|
@ -17,6 +17,6 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="http://flask.pocoo.org/">The Flask Website</a></li>
|
<li><a href="http://flask.pocoo.org/">The Flask Website</a></li>
|
||||||
<li><a href="http://pypi.python.org/pypi/Flask">Flask @ PyPI</a></li>
|
<li><a href="http://pypi.python.org/pypi/Flask">Flask @ PyPI</a></li>
|
||||||
<li><a href="http://github.com/mitsuhiko/flask">Flask @ github</a></li>
|
<li><a href="http://github.com/mitsuhiko/flask">Flask @ GitHub</a></li>
|
||||||
<li><a href="http://github.com/mitsuhiko/flask/issues">Issue Tracker</a></li>
|
<li><a href="http://github.com/mitsuhiko/flask/issues">Issue Tracker</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ depending on how the extension is distributed. If you want to develop an
|
||||||
application that supports Flask 0.7 or earlier you should still import
|
application that supports Flask 0.7 or earlier you should still import
|
||||||
from the :data:`flask.ext` package. We provide you with a compatibility
|
from the :data:`flask.ext` package. We provide you with a compatibility
|
||||||
module that provides this package for older versions of Flask. You can
|
module that provides this package for older versions of Flask. You can
|
||||||
download it from github: `flaskext_compat.py`_
|
download it from GitHub: `flaskext_compat.py`_
|
||||||
|
|
||||||
And here is how you can use it::
|
And here is how you can use it::
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ What does "micro" mean?
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
“Micro” does not mean that your whole web application has to fit into a single
|
“Micro” does not mean that your whole web application has to fit into a single
|
||||||
Python file, although it certainly can. Nor does it mean that Flask is lacking
|
Python file (although it certainly can), nor does it mean that Flask is lacking
|
||||||
in functionality. The "micro" in microframework means Flask aims to keep the
|
in functionality. The "micro" in microframework means Flask aims to keep the
|
||||||
core simple but extensible. Flask won't make many decisions for you, such as
|
core simple but extensible. Flask won't make many decisions for you, such as
|
||||||
what database to use. Those decisions that it does make, such as what
|
what database to use. Those decisions that it does make, such as what
|
||||||
|
|
@ -28,9 +28,9 @@ Configuration and Conventions
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
Flask has many configuration values, with sensible defaults, and a few
|
Flask has many configuration values, with sensible defaults, and a few
|
||||||
conventions when getting started. By convention templates and static files are
|
conventions when getting started. By convention, templates and static files are
|
||||||
stored in subdirectories within the application's Python source tree, with the
|
stored in subdirectories within the application's Python source tree, with the
|
||||||
names :file:`templates` and :file:`static` respectively. While this can be changed you
|
names :file:`templates` and :file:`static` respectively. While this can be changed, you
|
||||||
usually don't have to, especially when getting started.
|
usually don't have to, especially when getting started.
|
||||||
|
|
||||||
Growing with Flask
|
Growing with Flask
|
||||||
|
|
|
||||||
|
|
@ -165,4 +165,4 @@ explanation of the little bit of code above:
|
||||||
If you don't get the whole picture, download the `sourcecode
|
If you don't get the whole picture, download the `sourcecode
|
||||||
for this example
|
for this example
|
||||||
<https://github.com/mitsuhiko/flask/tree/master/examples/jqueryexample>`_
|
<https://github.com/mitsuhiko/flask/tree/master/examples/jqueryexample>`_
|
||||||
from github.
|
from GitHub.
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ Step 7: Adding Style
|
||||||
====================
|
====================
|
||||||
|
|
||||||
Now that everything else works, it's time to add some style to the
|
Now that everything else works, it's time to add some style to the
|
||||||
application. Just create a stylesheet called :file:`style.css` in the :file:`static`
|
application. Just create a stylesheet called :file:`style.css` in the
|
||||||
folder we created before:
|
:file:`static` folder we created before:
|
||||||
|
|
||||||
.. sourcecode:: css
|
.. sourcecode:: css
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,29 +4,29 @@ Step 3: Database Connections
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
We have created a function for establishing a database connection with
|
We have created a function for establishing a database connection with
|
||||||
`connect_db` but by itself that's not particularly useful. Creating and
|
`connect_db`, but by itself, that's not particularly useful. Creating and
|
||||||
closing database connections all the time is very inefficient, so we want
|
closing database connections all the time is very inefficient, so we want
|
||||||
to keep it around for longer. Because database connections encapsulate a
|
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
|
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?
|
uses the connection. How can we elegantly do that with Flask?
|
||||||
|
|
||||||
This is where the application context comes into play. So let's start
|
This is where the application context comes into play, so let's start
|
||||||
there.
|
there.
|
||||||
|
|
||||||
Flask provides us with two contexts: the application context and the
|
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
|
request context. For the time being, all you have to know is that there
|
||||||
are special variables that use these. For instance the
|
are special variables that use these. For instance, the
|
||||||
:data:`~flask.request` variable is the request object associated with
|
:data:`~flask.request` variable is the request object associated with
|
||||||
the current request, whereas :data:`~flask.g` is a general purpose
|
the current request, whereas :data:`~flask.g` is a general purpose
|
||||||
variable associated with the current application context. We will go into
|
variable associated with the current application context. We will go into
|
||||||
the details of this a bit later.
|
the details of this a bit later.
|
||||||
|
|
||||||
For the time being all you have to know is that you can store information
|
For the time being, all you have to know is that you can store information
|
||||||
safely on the :data:`~flask.g` object.
|
safely on the :data:`~flask.g` object.
|
||||||
|
|
||||||
So when do you put it on there? To do that you can make a helper
|
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
|
function. The first time the function is called, it will create a database
|
||||||
connection for the current context and successive calls will return the
|
connection for the current context, and successive calls will return the
|
||||||
already established connection::
|
already established connection::
|
||||||
|
|
||||||
def get_db():
|
def get_db():
|
||||||
|
|
@ -39,7 +39,7 @@ already established connection::
|
||||||
|
|
||||||
|
|
||||||
So now we know how to connect, but how do we properly disconnect? For
|
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`
|
that, Flask provides us with the :meth:`~flask.Flask.teardown_appcontext`
|
||||||
decorator. It's executed every time the application context tears down::
|
decorator. It's executed every time the application context tears down::
|
||||||
|
|
||||||
@app.teardown_appcontext
|
@app.teardown_appcontext
|
||||||
|
|
@ -49,11 +49,11 @@ decorator. It's executed every time the application context tears down::
|
||||||
g.sqlite_db.close()
|
g.sqlite_db.close()
|
||||||
|
|
||||||
Functions marked with :meth:`~flask.Flask.teardown_appcontext` are called
|
Functions marked with :meth:`~flask.Flask.teardown_appcontext` are called
|
||||||
every time the app context tears down. So what does this mean?
|
every time the app context tears down. What does this mean?
|
||||||
Essentially the app context is created before the request comes in and is
|
Essentially, the app context is created before the request comes in and is
|
||||||
destroyed (torn down) whenever the request finishes. A teardown can
|
destroyed (torn down) whenever the request finishes. A teardown can
|
||||||
happen because of two reasons: either everything went well (the error
|
happen because of two reasons: either everything went well (the error
|
||||||
parameter will be ``None``) or an exception happened in which case the error
|
parameter will be ``None``) or an exception happened, in which case the error
|
||||||
is passed to the teardown function.
|
is passed to the teardown function.
|
||||||
|
|
||||||
Curious about what these contexts mean? Have a look at the
|
Curious about what these contexts mean? Have a look at the
|
||||||
|
|
|
||||||
|
|
@ -5,24 +5,24 @@ Step 4: Creating The Database
|
||||||
|
|
||||||
As outlined earlier, Flaskr is a database powered application, and more
|
As outlined earlier, Flaskr is a database powered application, and more
|
||||||
precisely, it is an application powered by a relational database system. Such
|
precisely, it is an application powered by a relational database system. Such
|
||||||
systems need a schema that tells them how to store that information. So
|
systems need a schema that tells them how to store that information.
|
||||||
before starting the server for the first time it's important to create
|
Before starting the server for the first time, it's important to create
|
||||||
that schema.
|
that schema.
|
||||||
|
|
||||||
Such a schema can be created by piping the `schema.sql` file into the
|
Such a schema can be created by piping the ``schema.sql`` file into the
|
||||||
`sqlite3` command as follows::
|
`sqlite3` command as follows::
|
||||||
|
|
||||||
sqlite3 /tmp/flaskr.db < schema.sql
|
sqlite3 /tmp/flaskr.db < schema.sql
|
||||||
|
|
||||||
The downside of this is that it requires the sqlite3 command to be
|
The downside of this is that it requires the ``sqlite3`` command to be
|
||||||
installed which is not necessarily the case on every system. This also
|
installed, which is not necessarily the case on every system. This also
|
||||||
requires that we provide the path to the database which can introduce
|
requires that we provide the path to the database, which can introduce
|
||||||
errors. It's a good idea to add a function that initializes the database
|
errors. It's a good idea to add a function that initializes the database
|
||||||
for you to the application.
|
for you to the application.
|
||||||
|
|
||||||
To do this we can create a function and hook it into the :command:`flask` command
|
To do this, we can create a function and hook it into the :command:`flask`
|
||||||
that initializes the database. Let me show you the code first. Just add
|
command that initializes the database. Let me show you the code first. Just
|
||||||
this function below the `connect_db` function in :file:`flaskr.py`::
|
add this function below the `connect_db` function in :file:`flaskr.py`::
|
||||||
|
|
||||||
def init_db():
|
def init_db():
|
||||||
db = get_db()
|
db = get_db()
|
||||||
|
|
@ -37,36 +37,36 @@ this function below the `connect_db` function in :file:`flaskr.py`::
|
||||||
print 'Initialized the database.'
|
print 'Initialized the database.'
|
||||||
|
|
||||||
The ``app.cli.command()`` decorator registers a new command with the
|
The ``app.cli.command()`` decorator registers a new command with the
|
||||||
:command:`flask` script. When the command executes Flask will automatically
|
:command:`flask` script. When the command executes, Flask will automatically
|
||||||
create a application context for us bound to the right application.
|
create a application context for us bound to the right application.
|
||||||
Within the function we can then access :attr:`flask.g` and other things as
|
Within the function, we can then access :attr:`flask.g` and other things as
|
||||||
we would expect. When the script ends, the application context tears down
|
we would expect. When the script ends, the application context tears down
|
||||||
and the database connection is released.
|
and the database connection is released.
|
||||||
|
|
||||||
We want to keep an actual functions around that initializes the database
|
We want to keep an actual functions around that initializes the database,
|
||||||
though so that we can easily create databases in unittests later. (For
|
though, so that we can easily create databases in unit tests later on. (For
|
||||||
more information see :ref:`testing`.)
|
more information see :ref:`testing`.)
|
||||||
|
|
||||||
The :func:`~flask.Flask.open_resource` method of the application object
|
The :func:`~flask.Flask.open_resource` method of the application object
|
||||||
is a convenient helper function that will open a resource that the
|
is a convenient helper function that will open a resource that the
|
||||||
application provides. This function opens a file from the resource
|
application provides. This function opens a file from the resource
|
||||||
location (your `flaskr` folder) and allows you to read from it. We are
|
location (your ``flaskr`` folder) and allows you to read from it. We are
|
||||||
using this here to execute a script on the database connection.
|
using this here to execute a script on the database connection.
|
||||||
|
|
||||||
The connection object provided by SQLite can give us a cursor object.
|
The connection object provided by SQLite can give us a cursor object.
|
||||||
On that cursor there is a method to execute a complete script. Finally we
|
On that cursor, there is a method to execute a complete script. Finally, we
|
||||||
only have to commit the changes. SQLite 3 and other transactional
|
only have to commit the changes. SQLite3 and other transactional
|
||||||
databases will not commit unless you explicitly tell it to.
|
databases will not commit unless you explicitly tell it to.
|
||||||
|
|
||||||
Now it is possible to create a database with the :command:`flask` script::
|
Now, it is possible to create a database with the :command:`flask` script::
|
||||||
|
|
||||||
flask --app=flaskr initdb
|
flask --app=flaskr initdb
|
||||||
Initialized the database.
|
Initialized the database.
|
||||||
|
|
||||||
.. admonition:: Troubleshooting
|
.. admonition:: Troubleshooting
|
||||||
|
|
||||||
If you get an exception later that a table cannot be found check that
|
If you get an exception later on stating that a table cannot be found, check
|
||||||
you did execute the `initdb` command and that your table names are
|
that you did execute the ``initdb`` command and that your table names are
|
||||||
correct (singular vs. plural for example).
|
correct (singular vs. plural, for example).
|
||||||
|
|
||||||
Continue with :ref:`tutorial-views`
|
Continue with :ref:`tutorial-views`
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,13 @@ application::
|
||||||
/static
|
/static
|
||||||
/templates
|
/templates
|
||||||
|
|
||||||
The `flaskr` folder is not a python package, but just something where we
|
The ``flaskr`` folder is not a Python package, but just something where we
|
||||||
drop our files. We will then put our database schema as well as main module
|
drop our files. Later on, we will put our database schema as well as main
|
||||||
into this folder. It is done in the following way. The files inside
|
module into this folder. It is done in the following way. The files inside
|
||||||
the :file:`static` folder are available to users of the application via HTTP.
|
the :file:`static` folder are available to users of the application via HTTP.
|
||||||
This is the place where css and javascript files go. Inside the
|
This is the place where CSS and Javascript files go. Inside the
|
||||||
:file:`templates` folder Flask will look for `Jinja2`_ templates. The
|
:file:`templates` folder, Flask will look for `Jinja2`_ templates. The
|
||||||
templates you create later in the tutorial will go in this directory.
|
templates you create later on in the tutorial will go in this directory.
|
||||||
|
|
||||||
Continue with :ref:`tutorial-schema`.
|
Continue with :ref:`tutorial-schema`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ Tutorial
|
||||||
========
|
========
|
||||||
|
|
||||||
You want to develop an application with Python and Flask? Here you have
|
You want to develop an application with Python and Flask? Here you have
|
||||||
the chance to learn that by example. In this tutorial we will create a
|
the chance to learn by example. In this tutorial, we will create a simple
|
||||||
simple microblog application. It only supports one user that can create
|
microblogging application. It only supports one user that can create
|
||||||
text-only entries and there are no feeds or comments, but it still
|
text-only entries and there are no feeds or comments, but it still
|
||||||
features everything you need to get started. We will use Flask and SQLite
|
features everything you need to get started. We will use Flask and SQLite
|
||||||
as database which comes out of the box with Python, so there is nothing
|
as a database (which comes out of the box with Python) so there is nothing
|
||||||
else you need.
|
else you need.
|
||||||
|
|
||||||
If you want the full source code in advance or for comparison, check out
|
If you want the full source code in advance or for comparison, check out
|
||||||
|
|
|
||||||
|
|
@ -3,25 +3,25 @@
|
||||||
Introducing Flaskr
|
Introducing Flaskr
|
||||||
==================
|
==================
|
||||||
|
|
||||||
We will call our blogging application flaskr here, feel free to choose a
|
We will call our blogging application flaskr, but feel free to choose your own
|
||||||
less web-2.0-ish name ;) Basically we want it to do the following things:
|
less Web-2.0-ish name ;) Essentially, we want it to do the following things:
|
||||||
|
|
||||||
1. let the user sign in and out with credentials specified in the
|
1. Let the user sign in and out with credentials specified in the
|
||||||
configuration. Only one user is supported.
|
configuration. Only one user is supported.
|
||||||
2. when the user is logged in they can add new entries to the page
|
2. When the user is logged in, they can add new entries to the page
|
||||||
consisting of a text-only title and some HTML for the text. This HTML
|
consisting of a text-only title and some HTML for the text. This HTML
|
||||||
is not sanitized because we trust the user here.
|
is not sanitized because we trust the user here.
|
||||||
3. the page shows all entries so far in reverse order (newest on top) and
|
3. The index page shows all entries so far in reverse chronological order
|
||||||
the user can add new ones from there if logged in.
|
(newest on top) and the user can add new ones from there if logged in.
|
||||||
|
|
||||||
We will be using SQLite3 directly for that application because it's good
|
We will be using SQLite3 directly for this application because it's good
|
||||||
enough for an application of that size. For larger applications however
|
enough for an application of this size. For larger applications, however,
|
||||||
it makes a lot of sense to use `SQLAlchemy`_ that handles database
|
it makes a lot of sense to use `SQLAlchemy`_, as it handles database
|
||||||
connections in a more intelligent way, allows you to target different
|
connections in a more intelligent way, allowing you to target different
|
||||||
relational databases at once and more. You might also want to consider
|
relational databases at once and more. You might also want to consider
|
||||||
one of the popular NoSQL databases if your data is more suited for those.
|
one of the popular NoSQL databases if your data is more suited for those.
|
||||||
|
|
||||||
Here a screenshot from the final application:
|
Here a screenshot of the final application:
|
||||||
|
|
||||||
.. image:: ../_static/flaskr.png
|
.. image:: ../_static/flaskr.png
|
||||||
:align: center
|
:align: center
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
Step 1: Database Schema
|
Step 1: Database Schema
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
First we want to create the database schema. Only a single table is needed
|
First, we want to create the database schema. Only a single table is needed
|
||||||
for this application and we only want to support SQLite so creating the
|
for this application and we only want to support SQLite, so creating the
|
||||||
database schema is quite easy. Just put the following contents into a file
|
database schema is quite easy. Just put the following contents into a file
|
||||||
named `schema.sql` in the just created `flaskr` folder:
|
named `schema.sql` in the just created `flaskr` folder:
|
||||||
|
|
||||||
|
|
@ -17,8 +17,8 @@ named `schema.sql` in the just created `flaskr` folder:
|
||||||
'text' text not null
|
'text' text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
This schema consists of a single table called `entries` and each row in
|
This schema consists of a single table called ``entries``. Each row in
|
||||||
this table has an `id`, a `title` and a `text`. The `id` is an
|
this table has an ``id``, a ``title``, and a ``text``. The ``id`` is an
|
||||||
automatically incrementing integer and a primary key, the other two are
|
automatically incrementing integer and a primary key, the other two are
|
||||||
strings that must not be null.
|
strings that must not be null.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,15 @@
|
||||||
Step 2: Application Setup Code
|
Step 2: Application Setup Code
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
Now that we have the schema in place we can create the application module.
|
Now that we have the schema in place, we can create the application module.
|
||||||
Let's call it flaskr.py. We will place this file inside the flaskr folder.
|
Let's call it ``flaskr.py``. We will place this file inside the ``flaskr``
|
||||||
We will begin by adding the imports we need and by adding the config
|
folder. We will begin by adding the imports we need and by adding the config
|
||||||
section. For small applications, it is possible to drop the configuration
|
section. For small applications, it is possible to drop the configuration
|
||||||
directly into the module, and this is what we will be doing here. However
|
directly into the module, and this is what we will be doing here. However,
|
||||||
a cleaner solution would be to create a separate ``.ini`` or ``.py`` file and
|
a cleaner solution would be to create a separate ``.ini`` or ``.py`` file,
|
||||||
load that or import the values from there.
|
load that, and import the values from there.
|
||||||
|
|
||||||
First we add the imports in :file:`flaskr.py`::
|
First, we add the imports in :file:`flaskr.py`::
|
||||||
|
|
||||||
# all the imports
|
# all the imports
|
||||||
import os
|
import os
|
||||||
|
|
@ -19,8 +19,8 @@ First we add the imports in :file:`flaskr.py`::
|
||||||
from flask import Flask, request, session, g, redirect, url_for, abort, \
|
from flask import Flask, request, session, g, redirect, url_for, abort, \
|
||||||
render_template, flash
|
render_template, flash
|
||||||
|
|
||||||
Next we can create our actual application and initialize it with the
|
Next, we can create our actual application and initialize it with the
|
||||||
config from the same file, in :file:`flaskr.py`::
|
config from the same file in :file:`flaskr.py`::
|
||||||
|
|
||||||
# create our little application :)
|
# create our little application :)
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
@ -35,45 +35,47 @@ config from the same file, in :file:`flaskr.py`::
|
||||||
))
|
))
|
||||||
app.config.from_envvar('FLASKR_SETTINGS', silent=True)
|
app.config.from_envvar('FLASKR_SETTINGS', silent=True)
|
||||||
|
|
||||||
The :class:`~flask.Config` object works similar to a dictionary so we
|
The :class:`~flask.Config` object works similarly to a dictionary so we
|
||||||
can update it with new values.
|
can update it with new values.
|
||||||
|
|
||||||
.. admonition:: Database Path
|
.. admonition:: Database Path
|
||||||
|
|
||||||
Operating systems know the concept of a current working directory for
|
Operating systems know the concept of a current working directory for
|
||||||
each process. Unfortunately you cannot depend on this in web
|
each process. Unfortunately, you cannot depend on this in web
|
||||||
applications because you might have more than one application in the
|
applications because you might have more than one application in the
|
||||||
same process.
|
same process.
|
||||||
|
|
||||||
For this reason the ``app.root_path`` attribute can be used to
|
For this reason the ``app.root_path`` attribute can be used to
|
||||||
get the path to the application. Together with the ``os.path`` module
|
get the path to the application. Together with the ``os.path`` module,
|
||||||
files can then easily be found. In this example we place the
|
files can then easily be found. In this example, we place the
|
||||||
database right next to it.
|
database right next to it.
|
||||||
|
|
||||||
For a real-work application it's recommended to use
|
For a real-world application, it's recommended to use
|
||||||
:ref:`instance-folders` instead.
|
:ref:`instance-folders` instead.
|
||||||
|
|
||||||
Usually, it is a good idea to load a separate, environment specific
|
Usually, it is a good idea to load a separate, environment-specific
|
||||||
configuration file. Flask allows you to import multiple configurations and it
|
configuration file. Flask allows you to import multiple configurations and it
|
||||||
will use the setting defined in the last import. This enables robust
|
will use the setting defined in the last import. This enables robust
|
||||||
configuration setups. :meth:`~flask.Config.from_envvar` can help achieve this.
|
configuration setups. :meth:`~flask.Config.from_envvar` can help achieve this.
|
||||||
|
|
||||||
app.config.from_envvar('FLASKR_SETTINGS', silent=True)
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.config.from_envvar('FLASKR_SETTINGS', silent=True)
|
||||||
|
|
||||||
Simply define the environment variable :envvar:`FLASKR_SETTINGS` that points to
|
Simply define the environment variable :envvar:`FLASKR_SETTINGS` that points to
|
||||||
a config file to be loaded. The silent switch just tells Flask to not complain
|
a config file to be loaded. The silent switch just tells Flask to not complain
|
||||||
if no such environment key is set.
|
if no such environment key is set.
|
||||||
|
|
||||||
In addition to that you can use the :meth:`~flask.Config.from_object`
|
In addition to that, you can use the :meth:`~flask.Config.from_object`
|
||||||
method on the config object and provide it with an import name of a
|
method on the config object and provide it with an import name of a
|
||||||
module. Flask will then initialize the variable from that module. Note
|
module. Flask will then initialize the variable from that module. Note
|
||||||
that in all cases only variable names that are uppercase are considered.
|
that in all cases, only variable names that are uppercase are considered.
|
||||||
|
|
||||||
The ``SECRET_KEY`` is needed to keep the client-side sessions secure.
|
The ``SECRET_KEY`` is needed to keep the client-side sessions secure.
|
||||||
Choose that key wisely and as hard to guess and complex as possible.
|
Choose that key wisely and as hard to guess and complex as possible.
|
||||||
|
|
||||||
We will also add a method that allows for easily connecting to the
|
We will also add a method that allows for easy connections to the
|
||||||
specified database. This can be used to open a connection on request and
|
specified database. This can be used to open a connection on request and
|
||||||
also from the interactive Python shell or a script. This will come in
|
also from the interactive Python shell or a script. This will come in
|
||||||
handy later. We create a simple database connection through SQLite and
|
handy later. We create a simple database connection through SQLite and
|
||||||
then tell it to use the :class:`sqlite3.Row` object to represent rows.
|
then tell it to use the :class:`sqlite3.Row` object to represent rows.
|
||||||
|
|
@ -88,7 +90,7 @@ tuples.
|
||||||
rv.row_factory = sqlite3.Row
|
rv.row_factory = sqlite3.Row
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
With that out of the way you should be able to start up the application
|
With that out of the way, you should be able to start up the application
|
||||||
without problems. Do this with the following command::
|
without problems. Do this with the following command::
|
||||||
|
|
||||||
flask --app=flaskr --debug run
|
flask --app=flaskr --debug run
|
||||||
|
|
@ -100,9 +102,9 @@ users to execute code on the server!
|
||||||
You will see a message telling you that server has started along with
|
You will see a message telling you that server has started along with
|
||||||
the address at which you can access it.
|
the address at which you can access it.
|
||||||
|
|
||||||
When you head over to the server in your browser you will get an 404
|
When you head over to the server in your browser, you will get a 404 error
|
||||||
page not found error because we don't have any views yet. But we will
|
because we don't have any views yet. We will focus on that a little later,
|
||||||
focus on that a little later. First we should get the database working.
|
but first, we should get the database working.
|
||||||
|
|
||||||
.. admonition:: Externally Visible Server
|
.. admonition:: Externally Visible Server
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
Step 6: The Templates
|
Step 6: The Templates
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
Now we should start working on the templates. If we request the URLs now
|
Now we should start working on the templates. If we were torequest the URLs
|
||||||
we would only get an exception that Flask cannot find the templates. The
|
now, we would only get an exception that Flask cannot find the templates. The
|
||||||
templates are using `Jinja2`_ syntax and have autoescaping enabled by
|
templates are using `Jinja2`_ syntax and have autoescaping enabled by
|
||||||
default. This means that unless you mark a value in the code with
|
default. This means that unless you mark a value in the code with
|
||||||
:class:`~flask.Markup` or with the ``|safe`` filter in the template,
|
:class:`~flask.Markup` or with the ``|safe`` filter in the template,
|
||||||
|
|
@ -88,7 +88,7 @@ method:
|
||||||
login.html
|
login.html
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Finally the login template which basically just displays a form to allow
|
This is the login template, which basically just displays a form to allow
|
||||||
the user to login:
|
the user to login:
|
||||||
|
|
||||||
.. sourcecode:: html+jinja
|
.. sourcecode:: html+jinja
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,5 @@ Bonus: Testing the Application
|
||||||
Now that you have finished the application and everything works as
|
Now that you have finished the application and everything works as
|
||||||
expected, it's probably not a bad idea to add automated tests to simplify
|
expected, it's probably not a bad idea to add automated tests to simplify
|
||||||
modifications in the future. The application above is used as a basic
|
modifications in the future. The application above is used as a basic
|
||||||
example of how to perform unittesting in the :ref:`testing` section of the
|
example of how to perform unit testing in the :ref:`testing` section of the
|
||||||
documentation. Go there to see how easy it is to test Flask applications.
|
documentation. Go there to see how easy it is to test Flask applications.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
Step 5: The View Functions
|
Step 5: The View Functions
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
Now that the database connections are working we can start writing the
|
Now that the database connections are working, we can start writing the
|
||||||
view functions. We will need four of them:
|
view functions. We will need four of them:
|
||||||
|
|
||||||
Show Entries
|
Show Entries
|
||||||
|
|
@ -15,7 +15,7 @@ The one with the highest id (the newest entry) will be on top. The rows
|
||||||
returned from the cursor look a bit like tuples because we are using
|
returned from the cursor look a bit like tuples because we are using
|
||||||
the :class:`sqlite3.Row` row factory.
|
the :class:`sqlite3.Row` row factory.
|
||||||
|
|
||||||
The view function will pass the entries as dicts to the
|
The view function will pass the entries as dictionaries to the
|
||||||
:file:`show_entries.html` template and return the rendered one::
|
:file:`show_entries.html` template and return the rendered one::
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
|
|
@ -29,8 +29,8 @@ Add New Entry
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
This view lets the user add new entries if they are logged in. This only
|
This view lets the user add new entries if they are logged in. This only
|
||||||
responds to ``POST`` requests, the actual form is shown on the
|
responds to ``POST`` requests; the actual form is shown on the
|
||||||
`show_entries` page. If everything worked out well we will
|
`show_entries` page. If everything worked out well, we will
|
||||||
:func:`~flask.flash` an information message to the next request and
|
:func:`~flask.flash` an information message to the next request and
|
||||||
redirect back to the `show_entries` page::
|
redirect back to the `show_entries` page::
|
||||||
|
|
||||||
|
|
@ -60,7 +60,7 @@ Login and Logout
|
||||||
|
|
||||||
These functions are used to sign the user in and out. Login checks the
|
These functions are used to sign the user in and out. Login checks the
|
||||||
username and password against the ones from the configuration and sets the
|
username and password against the ones from the configuration and sets the
|
||||||
`logged_in` key in the session. If the user logged in successfully, that
|
`logged_in` key for the session. If the user logged in successfully, that
|
||||||
key is set to ``True``, and the user is redirected back to the `show_entries`
|
key is set to ``True``, and the user is redirected back to the `show_entries`
|
||||||
page. In addition, a message is flashed that informs the user that he or
|
page. In addition, a message is flashed that informs the user that he or
|
||||||
she was logged in successfully. If an error occurred, the template is
|
she was logged in successfully. If an error occurred, the template is
|
||||||
|
|
@ -80,7 +80,7 @@ notified about that, and the user is asked again::
|
||||||
return redirect(url_for('show_entries'))
|
return redirect(url_for('show_entries'))
|
||||||
return render_template('login.html', error=error)
|
return render_template('login.html', error=error)
|
||||||
|
|
||||||
The logout function, on the other hand, removes that key from the session
|
The `logout` function, on the other hand, removes that key from the session
|
||||||
again. We use a neat trick here: if you use the :meth:`~dict.pop` method
|
again. We use a neat trick here: if you use the :meth:`~dict.pop` method
|
||||||
of the dict and pass a second parameter to it (the default), the method
|
of the dict and pass a second parameter to it (the default), the method
|
||||||
will delete the key from the dictionary if present or do nothing when that
|
will delete the key from the dictionary if present or do nothing when that
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue