Browse Source

Merge pull request #1277 from iKevinY/doc-fixes

Documentation fixes (mostly in Tutorial)
pull/1285/head
Markus Unterwaditzer 10 years ago
parent
commit
82d7c49d00
  1. 2
      docs/_templates/sidebarintro.html
  2. 2
      docs/extensions.rst
  3. 6
      docs/foreword.rst
  4. 2
      docs/patterns/jquery.rst
  5. 4
      docs/tutorial/css.rst
  6. 26
      docs/tutorial/dbcon.rst
  7. 40
      docs/tutorial/dbinit.rst
  8. 12
      docs/tutorial/folders.rst
  9. 6
      docs/tutorial/index.rst
  10. 22
      docs/tutorial/introduction.rst
  11. 8
      docs/tutorial/schema.rst
  12. 50
      docs/tutorial/setup.rst
  13. 6
      docs/tutorial/templates.rst
  14. 2
      docs/tutorial/testing.rst
  15. 12
      docs/tutorial/views.rst

2
docs/_templates/sidebarintro.html vendored

@ -17,6 +17,6 @@
<ul>
<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://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>
</ul>

2
docs/extensions.rst

@ -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
from the :data:`flask.ext` package. We provide you with a compatibility
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::

6
docs/foreword.rst

@ -9,7 +9,7 @@ What does "micro" mean?
-----------------------
“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
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
@ -28,9 +28,9 @@ Configuration and Conventions
-----------------------------
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
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.
Growing with Flask

2
docs/patterns/jquery.rst

@ -165,4 +165,4 @@ explanation of the little bit of code above:
If you don't get the whole picture, download the `sourcecode
for this example
<https://github.com/mitsuhiko/flask/tree/master/examples/jqueryexample>`_
from github.
from GitHub.

4
docs/tutorial/css.rst

@ -4,8 +4,8 @@ Step 7: Adding Style
====================
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`
folder we created before:
application. Just create a stylesheet called :file:`style.css` in the
:file:`static` folder we created before:
.. sourcecode:: css

26
docs/tutorial/dbcon.rst

@ -4,29 +4,29 @@ Step 3: Database Connections
----------------------------
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
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?
transaction, we also need to make sure that only one request at the time
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.
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
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.
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.
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
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::
def get_db():
@ -39,7 +39,7 @@ already established connection::
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::
@app.teardown_appcontext
@ -49,11 +49,11 @@ decorator. It's executed every time the application context tears down::
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
every time the app context tears down. What does this mean?
Essentially, the app context is created before the request comes in and is
destroyed (torn 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 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.
Curious about what these contexts mean? Have a look at the

40
docs/tutorial/dbinit.rst

@ -5,24 +5,24 @@ Step 4: Creating The Database
As outlined earlier, Flaskr is a database powered application, and more
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
before starting the server for the first time it's important to create
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
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 /tmp/flaskr.db < schema.sql
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
requires that we provide the path to the database which can introduce
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
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
for you to the application.
To do this we can create a function and hook it into the :command:`flask` command
that initializes the database. Let me show you the code first. Just add
this function below the `connect_db` function in :file:`flaskr.py`::
To do this, we can create a function and hook it into the :command:`flask`
command that initializes the database. Let me show you the code first. Just
add this function below the `connect_db` function in :file:`flaskr.py`::
def init_db():
db = get_db()
@ -37,36 +37,36 @@ this function below the `connect_db` function in :file:`flaskr.py`::
print 'Initialized the database.'
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.
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
and the database connection is released.
We want to keep an actual functions around that initializes the database
though so that we can easily create databases in unittests later. (For
We want to keep an actual functions around that initializes the database,
though, so that we can easily create databases in unit tests later on. (For
more information see :ref:`testing`.)
The :func:`~flask.Flask.open_resource` method of the application object
is a convenient helper function that will open a resource that the
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.
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
only have to commit the changes. SQLite 3 and other transactional
On that cursor, there is a method to execute a complete script. Finally, we
only have to commit the changes. SQLite3 and other transactional
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
Initialized the database.
.. admonition:: Troubleshooting
If you get an exception later that a table cannot be found check that
you did execute the `initdb` command and that your table names are
correct (singular vs. plural for example).
If you get an exception later on stating that a table cannot be found, check
that you did execute the ``initdb`` command and that your table names are
correct (singular vs. plural, for example).
Continue with :ref:`tutorial-views`

12
docs/tutorial/folders.rst

@ -10,13 +10,13 @@ application::
/static
/templates
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
into this folder. It is done in the following way. The files inside
The ``flaskr`` folder is not a Python package, but just something where we
drop our files. Later on, we will put our database schema as well as main
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.
This is the place where css and javascript files go. Inside the
:file:`templates` folder Flask will look for `Jinja2`_ templates. The
templates you create later in the tutorial will go in this directory.
This is the place where CSS and Javascript files go. Inside the
:file:`templates` folder, Flask will look for `Jinja2`_ templates. The
templates you create later on in the tutorial will go in this directory.
Continue with :ref:`tutorial-schema`.

6
docs/tutorial/index.rst

@ -4,11 +4,11 @@ Tutorial
========
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
simple microblog application. It only supports one user that can create
the chance to learn by example. In this tutorial, we will create a simple
microblogging application. It only supports one user that can create
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
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.
If you want the full source code in advance or for comparison, check out

22
docs/tutorial/introduction.rst

@ -3,25 +3,25 @@
Introducing Flaskr
==================
We will call our blogging application flaskr here, feel free to choose a
less web-2.0-ish name ;) Basically we want it to do the following things:
We will call our blogging application flaskr, but feel free to choose your own
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.
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
is not sanitized because we trust the user here.
3. the page shows all entries so far in reverse order (newest on top) and
the user can add new ones from there if logged in.
3. The index page shows all entries so far in reverse chronological order
(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
enough for an application of that size. For larger applications however
it makes a lot of sense to use `SQLAlchemy`_ that handles database
connections in a more intelligent way, allows you to target different
We will be using SQLite3 directly for this application because it's good
enough for an application of this size. For larger applications, however,
it makes a lot of sense to use `SQLAlchemy`_, as it handles database
connections in a more intelligent way, allowing you to target different
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.
Here a screenshot from the final application:
Here a screenshot of the final application:
.. image:: ../_static/flaskr.png
:align: center

8
docs/tutorial/schema.rst

@ -3,8 +3,8 @@
Step 1: Database Schema
=======================
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
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
database schema is quite easy. Just put the following contents into a file
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
);
This schema consists of a single table called `entries` and each row in
this table has an `id`, a `title` and a `text`. The `id` is an
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
automatically incrementing integer and a primary key, the other two are
strings that must not be null.

50
docs/tutorial/setup.rst

@ -3,15 +3,15 @@
Step 2: Application Setup Code
==============================
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.
We will begin by adding the imports we need and by adding the config
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. 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
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
load that or import the values from there.
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,
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
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, \
render_template, flash
Next we can create our actual application and initialize it with the
config from the same file, in :file:`flaskr.py`::
Next, we can create our actual application and initialize it with the
config from the same file in :file:`flaskr.py`::
# create our little application :)
app = Flask(__name__)
@ -35,45 +35,47 @@ config from the same file, in :file:`flaskr.py`::
))
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.
.. admonition:: Database Path
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
same process.
For this reason the ``app.root_path`` attribute can be used to
get the path to the application. Together with the ``os.path`` module
files can then easily be found. In this example we place the
get the path to the application. Together with the ``os.path`` module,
files can then easily be found. In this example, we place the
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.
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
will use the setting defined in the last import. This enables robust
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
a config file to be loaded. The silent switch just tells Flask to not complain
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
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.
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
specified database. This can be used to open a connection on request and
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
also from the interactive Python shell or a script. This will come in
handy later. We create a simple database connection through SQLite and
then tell it to use the :class:`sqlite3.Row` object to represent rows.
@ -88,7 +90,7 @@ tuples.
rv.row_factory = sqlite3.Row
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::
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
the address at which you can access it.
When you head over to the server in your browser you will get an 404
page not found error because we don't have any views yet. But we will
focus on that a little later. First we should get the database working.
When you head over to the server in your browser, you will get a 404 error
because we don't have any views yet. We will focus on that a little later,
but first, we should get the database working.
.. admonition:: Externally Visible Server

6
docs/tutorial/templates.rst

@ -3,8 +3,8 @@
Step 6: The Templates
=====================
Now we should start working on the templates. If we request the URLs now
we would only get an exception that Flask cannot find the templates. The
Now we should start working on the templates. If we were torequest the URLs
now, we would only get an exception that Flask cannot find the templates. The
templates are using `Jinja2`_ syntax and have autoescaping enabled by
default. This means that unless you mark a value in the code with
:class:`~flask.Markup` or with the ``|safe`` filter in the template,
@ -88,7 +88,7 @@ method:
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:
.. sourcecode:: html+jinja

2
docs/tutorial/testing.rst

@ -6,5 +6,5 @@ Bonus: Testing the Application
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
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.

12
docs/tutorial/views.rst

@ -3,7 +3,7 @@
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:
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
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::
@app.route('/')
@ -29,8 +29,8 @@ Add New Entry
-------------
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
`show_entries` page. If everything worked out well we will
responds to ``POST`` requests; the actual form is shown on the
`show_entries` page. If everything worked out well, we will
:func:`~flask.flash` an information message to the next request and
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
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`
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
@ -80,7 +80,7 @@ notified about that, and the user is asked again::
return redirect(url_for('show_entries'))
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
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

Loading…
Cancel
Save