Browse Source

Grammatical fixes in Foreword and Tutorial

pull/1277/head
Kevin Yap 10 years ago
parent
commit
23fc2e56a8
  1. 6
      docs/foreword.rst
  2. 4
      docs/tutorial/css.rst
  3. 26
      docs/tutorial/dbcon.rst
  4. 40
      docs/tutorial/dbinit.rst
  5. 12
      docs/tutorial/folders.rst
  6. 6
      docs/tutorial/index.rst
  7. 22
      docs/tutorial/introduction.rst
  8. 8
      docs/tutorial/schema.rst
  9. 50
      docs/tutorial/setup.rst
  10. 6
      docs/tutorial/templates.rst
  11. 2
      docs/tutorial/testing.rst
  12. 12
      docs/tutorial/views.rst

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 “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

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 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

26
docs/tutorial/dbcon.rst

@ -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

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 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`

12
docs/tutorial/folders.rst

@ -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`.

6
docs/tutorial/index.rst

@ -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

22
docs/tutorial/introduction.rst

@ -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

8
docs/tutorial/schema.rst

@ -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.

50
docs/tutorial/setup.rst

@ -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

6
docs/tutorial/templates.rst

@ -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

2
docs/tutorial/testing.rst

@ -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.

12
docs/tutorial/views.rst

@ -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…
Cancel
Save