From b1b92284f496800a4dfd2cea72cb9be07ba8661c Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Fri, 13 Sep 2013 16:52:14 -0400 Subject: First cut at import of quick tutorial. --- docs/quick_tutorial/databases.rst | 184 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 docs/quick_tutorial/databases.rst (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst new file mode 100644 index 000000000..d2d2ce699 --- /dev/null +++ b/docs/quick_tutorial/databases.rst @@ -0,0 +1,184 @@ +============================== +19: Databases Using SQLAlchemy +============================== + +Store/retrieve data using the SQLAlchemy ORM atop the SQLite database. + +Background +========== + +Our Pyramid-based wiki application now needs database-backed storage of +pages. This frequently means a SQL database. The Pyramid community +strongly supports the +:ref:`SQLAlchemy ` project and its +:ref:`object-relational mapper (ORM) ` +as a convenient, Pythonic way to interface to databases. + +In this step we hook up SQLAlchemy to a SQLite database table, +providing storage and retrieval for the wikipages in the previous step. + +.. note:: + + The ``alchemy`` scaffold is really helpful for getting a + SQLAlchemy project going, including generation of the console + script. Since we want to see all the decisions, we will forgo + convenience in this tutorial and wire it up ourselves. + +Objectives +========== + +- Store pages in SQLite by using SQLAlchemy models + +- Use SQLAlchemy queries to list/add/view/edit pages + +- Provide a database-initialize command by writing a Pyramid *console + script* which can be run from the command line + +Steps +===== + +#. We are going to use the forms step as our starting point: + + .. code-block:: bash + + (env27)$ cd ..; cp -r forms databases; cd databases + +#. We need to add some dependencies in ``databases/setup.py`` as well + as an "entry point" for the command-line script: + + .. literalinclude:: databases/setup.py + :linenos: + + .. note:: + + We aren't yet doing ``python3.3 setup.py develop`` as we + are changing it later. + +#. Our configuration file at ``databases/development.ini`` wires + together some new pieces: + + .. literalinclude:: databases/development.ini + :language: ini + +#. This engine configuration now needs to be read into the application + through changes in ``databases/tutorial/__init__.py``: + + .. literalinclude:: databases/tutorial/__init__.py + :linenos: + +#. Make a command-line script at ``databases/tutorial/initialize_db.py`` + to initialize the database: + + .. literalinclude:: databases/tutorial/initialize_db.py + +#. Since ``setup.py`` changed, we now run it: + + .. code-block:: bash + + (env27)$ python setup.py develop + +#. The script references some models in ``databases/tutorial/models.py``: + + .. literalinclude:: databases/tutorial/models.py + :linenos: + +#. Let's run this console script, thus producing our database and table: + + .. code-block:: bash + + (env27)$ initialize_tutorial_db development.ini + 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") + 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2013-09-06 15:54:08,051 INFO [sqlalchemy.engine.base.Engine][MainThread] + CREATE TABLE wikipages ( + uid INTEGER NOT NULL, + title TEXT, + body TEXT, + PRIMARY KEY (uid), + UNIQUE (title) + ) + +#. With our data now driven by SQLAlchemy queries, we need to update + our ``databases/tutorial/views.py``: + + .. literalinclude:: databases/tutorial/views.py + +#. Our tests in ``databases/tutorial/tests.py`` changed to include + SQLAlchemy bootstrapping: + + .. literalinclude:: databases/tutorial/tests.py + :linenos: + +#. Run the tests in your package using ``nose``: + + .. code-block:: bash + + (env27)$ nosetests . + .. + ----------------------------------------------------------------- + Ran 2 tests in 1.141s + + OK + +#. Run your Pyramid application with: + + .. code-block:: bash + + (env27)$ pserve development.ini --reload + +#. Open ``http://localhost:6543/`` in a browser. + +Analysis +======== + +Let's start with the dependencies. We made the decision to use +``SQLAlchemy`` to talk to our database. We also, though, installed +``pyramid_tm`` and ``zope.sqlalchemy``. Why? + +Pyramid has a strong orientation towards support for ``transactions``. +Specifically, you can install a transaction manager into your app +application, either as middleware or a Pyramid "tween". Then, +just before you return the response, all transaction-aware parts of +your application are executed. + +This means Pyramid view code usually doesn't manage transactions. If +your view code or a template generates an error, the transaction manager +aborts the transaction. This is a very liberating way to write code. + +The ``pyramid_tm`` package provides a "tween" that is configured in the +``development.ini`` configuration file. That installs it. We then need +a package that makes SQLAlchemy and thus the RDBMS transaction manager +integrate with the Pyramid transaction manager. That's what +``zope.sqlalchemy`` does. + +Where do we point at the location on disk for the SQLite file? In the +configuration file. This lets consumers of our package change the +location in a safe (non-code) way. That is, in configuration. This +configuration-oriented approach isn't required in Pyramid; you can +still make such statements in your ``__init__.py`` or some companion +module. + +The ``initialize_tutorial_db`` is a nice example of framework support. +You point your setup at the location of some ``[console_scripts]`` and +these get generated into your virtualenv's ``bin`` directory. Our +console script follows the pattern of being fed a configuration file +with all the bootstrapping. It then opens SQLAlchemy and creates the +root of the wiki, which also makes the SQLite file. Note the +``with transaction.manager`` part that puts the work in the scope of a +transaction (as we aren't inside a web request where this is done +automatically.) + +The ``models.py`` does a little bit extra work to hook up SQLAlchemy +into the Pyramid transaction manager. It then declares the model for a +``Page``. + +Our views have changes primarily around replacing our dummy +dictionary-of-dictionaries data with proper database support: list the +rows, add a row, edit a row, and delete a row. + +Extra Credit +============ + +#. Why all this code? Why can't I just type 2 lines and have magic ensue? + +#. Give a try at a button that deletes a wiki page. -- cgit v1.2.3 From 0a784868bdbc3a0eb226ed00e8d89cda9d181ec5 Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Fri, 13 Sep 2013 17:11:42 -0400 Subject: Fix naming of virtualenv prefix. --- docs/quick_tutorial/databases.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index d2d2ce699..ea03677b2 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -41,7 +41,7 @@ Steps .. code-block:: bash - (env27)$ cd ..; cp -r forms databases; cd databases + (env)$ cd ..; cp -r forms databases; cd databases #. We need to add some dependencies in ``databases/setup.py`` as well as an "entry point" for the command-line script: @@ -75,7 +75,7 @@ Steps .. code-block:: bash - (env27)$ python setup.py develop + (env)$ python setup.py develop #. The script references some models in ``databases/tutorial/models.py``: @@ -86,7 +86,7 @@ Steps .. code-block:: bash - (env27)$ initialize_tutorial_db development.ini + (env)$ initialize_tutorial_db development.ini 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] () 2013-09-06 15:54:08,051 INFO [sqlalchemy.engine.base.Engine][MainThread] @@ -113,7 +113,7 @@ Steps .. code-block:: bash - (env27)$ nosetests . + (env)$ nosetests . .. ----------------------------------------------------------------- Ran 2 tests in 1.141s @@ -124,7 +124,7 @@ Steps .. code-block:: bash - (env27)$ pserve development.ini --reload + (env)$ pserve development.ini --reload #. Open ``http://localhost:6543/`` in a browser. -- cgit v1.2.3 From b0b28ede912c817a62a84b97c332e39eda02d166 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Mon, 16 Sep 2013 02:14:53 +0200 Subject: s/env/venv just for sake of consistency --- docs/quick_tutorial/databases.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index ea03677b2..be7fbd029 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -41,7 +41,7 @@ Steps .. code-block:: bash - (env)$ cd ..; cp -r forms databases; cd databases + (venv)$ cd ..; cp -r forms databases; cd databases #. We need to add some dependencies in ``databases/setup.py`` as well as an "entry point" for the command-line script: @@ -75,7 +75,7 @@ Steps .. code-block:: bash - (env)$ python setup.py develop + (venv)$ python setup.py develop #. The script references some models in ``databases/tutorial/models.py``: @@ -86,7 +86,7 @@ Steps .. code-block:: bash - (env)$ initialize_tutorial_db development.ini + (venv)$ initialize_tutorial_db development.ini 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] () 2013-09-06 15:54:08,051 INFO [sqlalchemy.engine.base.Engine][MainThread] @@ -113,7 +113,7 @@ Steps .. code-block:: bash - (env)$ nosetests . + (venv)$ nosetests . .. ----------------------------------------------------------------- Ran 2 tests in 1.141s @@ -124,7 +124,7 @@ Steps .. code-block:: bash - (env)$ pserve development.ini --reload + (venv)$ pserve development.ini --reload #. Open ``http://localhost:6543/`` in a browser. -- cgit v1.2.3 From d749bf4c987c4ab90bd5f89326e7d4059e4f47b3 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Mon, 16 Sep 2013 02:18:11 +0200 Subject: make example links clickable, for convenience --- docs/quick_tutorial/databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index be7fbd029..e8786a046 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -126,7 +126,7 @@ Steps (venv)$ pserve development.ini --reload -#. Open ``http://localhost:6543/`` in a browser. +#. Open http://localhost:6543/ in a browser. Analysis ======== -- cgit v1.2.3 From 187104fd81418beeb51592913041d9751bafe08d Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Wed, 25 Sep 2013 09:27:43 -0400 Subject: Quick Tutorial: Improve the setup instructions (adapted from Steve Piercy's work), particularly for Windows. Change all the steps to use $VENV/bin prefixes on commands (don't presume that they have done source env/bin/activate). --- docs/quick_tutorial/databases.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index e8786a046..978ef6982 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -41,7 +41,7 @@ Steps .. code-block:: bash - (venv)$ cd ..; cp -r forms databases; cd databases + $ cd ..; cp -r forms databases; cd databases #. We need to add some dependencies in ``databases/setup.py`` as well as an "entry point" for the command-line script: @@ -75,7 +75,7 @@ Steps .. code-block:: bash - (venv)$ python setup.py develop + $ $VENV/bin/python setup.py develop #. The script references some models in ``databases/tutorial/models.py``: @@ -86,7 +86,7 @@ Steps .. code-block:: bash - (venv)$ initialize_tutorial_db development.ini + $ initialize_tutorial_db development.ini 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] () 2013-09-06 15:54:08,051 INFO [sqlalchemy.engine.base.Engine][MainThread] @@ -113,7 +113,7 @@ Steps .. code-block:: bash - (venv)$ nosetests . + $ $VENV/bin/nosetests . .. ----------------------------------------------------------------- Ran 2 tests in 1.141s @@ -124,7 +124,7 @@ Steps .. code-block:: bash - (venv)$ pserve development.ini --reload + $ $VENV/bin/pserve development.ini --reload #. Open http://localhost:6543/ in a browser. -- cgit v1.2.3 From 34e974e360184baef873da55f31379697e367f32 Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Wed, 25 Sep 2013 12:08:33 -0400 Subject: Get pyramid_chameleon added to the quick tutorial, plus some other fixes for Python 3. --- docs/quick_tutorial/databases.rst | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 978ef6982..83cf33862 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -37,6 +37,15 @@ Objectives Steps ===== +.. warning:: + + Your Python might not have SQLite bundled. If not, install it into + your virtual environment with: + + .. code-block:: bash + + $ $VENV/bin/easy_install sphinx pysqlite + #. We are going to use the forms step as our starting point: .. code-block:: bash -- cgit v1.2.3 From b731b5fca253d9d95b3307490aa585e194676c01 Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Thu, 26 Sep 2013 17:41:44 -0400 Subject: Quick Tour: shorten the setup part and point to Quick Tutorial Requirements for more explanation. Cross link each Quick Tour section with its Quick Tutorial match. --- docs/quick_tutorial/databases.rst | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 83cf33862..93a02ffc7 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -1,3 +1,5 @@ +.. _qtut_databases: + ============================== 19: Databases Using SQLAlchemy ============================== -- cgit v1.2.3 From a2b15855bee4893524609a941954c823bfbcec0d Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Tue, 8 Oct 2013 14:33:16 -0400 Subject: Small quick tutorial fixes post conference. --- docs/quick_tutorial/databases.rst | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 93a02ffc7..20b3cd46d 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -39,15 +39,6 @@ Objectives Steps ===== -.. warning:: - - Your Python might not have SQLite bundled. If not, install it into - your virtual environment with: - - .. code-block:: bash - - $ $VENV/bin/easy_install sphinx pysqlite - #. We are going to use the forms step as our starting point: .. code-block:: bash @@ -97,7 +88,7 @@ Steps .. code-block:: bash - $ initialize_tutorial_db development.ini + $ $VENV/bin/initialize_tutorial_db development.ini 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] () 2013-09-06 15:54:08,051 INFO [sqlalchemy.engine.base.Engine][MainThread] -- cgit v1.2.3 From c79c2d9f36f27abfa5e2a72e021298728734138d Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 25 May 2014 16:36:09 -0700 Subject: Bring in #1352 --- docs/quick_tutorial/databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 20b3cd46d..7c019dbfc 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -115,7 +115,7 @@ Steps .. code-block:: bash - $ $VENV/bin/nosetests . + $ $VENV/bin/nosetests tutorial .. ----------------------------------------------------------------- Ran 2 tests in 1.141s -- cgit v1.2.3 From c8e23eca583e1e3dd770951e820004a1477c4e11 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 23 May 2015 12:05:56 -0700 Subject: fix template static asset URLs; grammar; line numbers --- docs/quick_tutorial/databases.rst | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 7c019dbfc..580774163 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -53,8 +53,8 @@ Steps .. note:: - We aren't yet doing ``python3.3 setup.py develop`` as we - are changing it later. + We aren't yet doing ``$VENV/bin/python setup.py develop`` as we + will change it later. #. Our configuration file at ``databases/development.ini`` wires together some new pieces: @@ -72,6 +72,7 @@ Steps to initialize the database: .. literalinclude:: databases/tutorial/initialize_db.py + :linenos: #. Since ``setup.py`` changed, we now run it: @@ -104,6 +105,7 @@ Steps our ``databases/tutorial/views.py``: .. literalinclude:: databases/tutorial/views.py + :linenos: #. Our tests in ``databases/tutorial/tests.py`` changed to include SQLAlchemy bootstrapping: @@ -138,8 +140,8 @@ Let's start with the dependencies. We made the decision to use ``pyramid_tm`` and ``zope.sqlalchemy``. Why? Pyramid has a strong orientation towards support for ``transactions``. -Specifically, you can install a transaction manager into your app -application, either as middleware or a Pyramid "tween". Then, +Specifically, you can install a transaction manager into your +application either as middleware or a Pyramid "tween". Then, just before you return the response, all transaction-aware parts of your application are executed. @@ -149,7 +151,7 @@ aborts the transaction. This is a very liberating way to write code. The ``pyramid_tm`` package provides a "tween" that is configured in the ``development.ini`` configuration file. That installs it. We then need -a package that makes SQLAlchemy and thus the RDBMS transaction manager +a package that makes SQLAlchemy, and thus the RDBMS transaction manager, integrate with the Pyramid transaction manager. That's what ``zope.sqlalchemy`` does. @@ -167,8 +169,8 @@ console script follows the pattern of being fed a configuration file with all the bootstrapping. It then opens SQLAlchemy and creates the root of the wiki, which also makes the SQLite file. Note the ``with transaction.manager`` part that puts the work in the scope of a -transaction (as we aren't inside a web request where this is done -automatically.) +transaction, as we aren't inside a web request where this is done +automatically. The ``models.py`` does a little bit extra work to hook up SQLAlchemy into the Pyramid transaction manager. It then declares the model for a -- cgit v1.2.3 From 608f955e20723723f33750211bb12debf613819b Mon Sep 17 00:00:00 2001 From: Karen Dalton Date: Mon, 1 Jun 2015 12:54:43 -0700 Subject: Add additional logging configs necessary for db script output and update tests.py to fix the 'At least one scoped session' warning --- docs/quick_tutorial/databases.rst | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 580774163..19dfd066d 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -90,17 +90,29 @@ Steps .. code-block:: bash $ $VENV/bin/initialize_tutorial_db development.ini - 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") - 2013-09-06 15:54:08,050 INFO [sqlalchemy.engine.base.Engine][MainThread] () - 2013-09-06 15:54:08,051 INFO [sqlalchemy.engine.base.Engine][MainThread] + 2015-06-01 11:22:52,650 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1 + 2015-06-01 11:22:52,650 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2015-06-01 11:22:52,651 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1 + 2015-06-01 11:22:52,651 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2015-06-01 11:22:52,652 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") + 2015-06-01 11:22:52,652 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2015-06-01 11:22:52,653 INFO [sqlalchemy.engine.base.Engine][MainThread] CREATE TABLE wikipages ( - uid INTEGER NOT NULL, - title TEXT, - body TEXT, - PRIMARY KEY (uid), - UNIQUE (title) + uid INTEGER NOT NULL, + title TEXT, + body TEXT, + PRIMARY KEY (uid), + UNIQUE (title) ) + + 2015-06-01 11:22:52,653 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2015-06-01 11:22:52,655 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT + 2015-06-01 11:22:52,658 INFO [sqlalchemy.engine.base.Engine][MainThread] BEGIN (implicit) + 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] INSERT INTO wikipages (title, body) VALUES (?, ?) + 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] ('Root', '

Root

') + 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT + #. With our data now driven by SQLAlchemy queries, we need to update our ``databases/tutorial/views.py``: -- cgit v1.2.3 From a42b09be68e52d8204bc0f3c18697bb2020f8fc4 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 7 Apr 2016 03:31:34 -0700 Subject: - update databases.rst --- docs/quick_tutorial/databases.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 19dfd066d..311ff6ec5 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -53,7 +53,7 @@ Steps .. note:: - We aren't yet doing ``$VENV/bin/python setup.py develop`` as we + We aren't yet doing ``$VENV/bin/pip install -e .`` as we will change it later. #. Our configuration file at ``databases/development.ini`` wires @@ -78,7 +78,7 @@ Steps .. code-block:: bash - $ $VENV/bin/python setup.py develop + $ $VENV/bin/pip install -e . #. The script references some models in ``databases/tutorial/models.py``: -- cgit v1.2.3 From d67566acebf890a603fad0e9069d5e131dfb5b31 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Tue, 12 Apr 2016 06:43:38 -0700 Subject: one does not simply "create a virtualenv". one should "create a virtual environment". - Fixes #2483 --- docs/quick_tutorial/databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index 311ff6ec5..f9f548585 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -176,7 +176,7 @@ module. The ``initialize_tutorial_db`` is a nice example of framework support. You point your setup at the location of some ``[console_scripts]`` and -these get generated into your virtualenv's ``bin`` directory. Our +these get generated into your virtual environment's ``bin`` directory. Our console script follows the pattern of being fed a configuration file with all the bootstrapping. It then opens SQLAlchemy and creates the root of the wiki, which also makes the SQLite file. Note the -- cgit v1.2.3 From 8bca48a37f5a0f79976d975aa3afd5760688a89c Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 16 Apr 2016 13:22:31 -0700 Subject: quick_tutorial cleanup - replace nose with pytest - cleanup databases.rst --- docs/quick_tutorial/databases.rst | 186 +++++++++++++++++++------------------- 1 file changed, 92 insertions(+), 94 deletions(-) (limited to 'docs/quick_tutorial/databases.rst') diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst index f9f548585..c8d87c180 100644 --- a/docs/quick_tutorial/databases.rst +++ b/docs/quick_tutorial/databases.rst @@ -4,37 +4,39 @@ 19: Databases Using SQLAlchemy ============================== -Store/retrieve data using the SQLAlchemy ORM atop the SQLite database. +Store and retrieve data using the SQLAlchemy ORM atop the SQLite database. + Background ========== -Our Pyramid-based wiki application now needs database-backed storage of -pages. This frequently means a SQL database. The Pyramid community -strongly supports the -:ref:`SQLAlchemy ` project and its -:ref:`object-relational mapper (ORM) ` -as a convenient, Pythonic way to interface to databases. +Our Pyramid-based wiki application now needs database-backed storage of pages. +This frequently means an SQL database. The Pyramid community strongly supports +the :ref:`SQLAlchemy ` project and its +:ref:`object-relational mapper (ORM) ` as a +convenient, Pythonic way to interface to databases. -In this step we hook up SQLAlchemy to a SQLite database table, -providing storage and retrieval for the wikipages in the previous step. +In this step we hook up SQLAlchemy to a SQLite database table, providing +storage and retrieval for the wiki pages in the previous step. .. note:: - The ``alchemy`` scaffold is really helpful for getting a - SQLAlchemy project going, including generation of the console - script. Since we want to see all the decisions, we will forgo - convenience in this tutorial and wire it up ourselves. + The ``alchemy`` scaffold is really helpful for getting an SQLAlchemy + project going, including generation of the console script. Since we want to + see all the decisions, we will forgo convenience in this tutorial, and wire + it up ourselves. + Objectives ========== -- Store pages in SQLite by using SQLAlchemy models +- Store pages in SQLite by using SQLAlchemy models. -- Use SQLAlchemy queries to list/add/view/edit pages +- Use SQLAlchemy queries to list/add/view/edit pages. + +- Provide a database-initialize command by writing a Pyramid *console script* + which can be run from the command line. -- Provide a database-initialize command by writing a Pyramid *console - script* which can be run from the command line Steps ===== @@ -45,31 +47,31 @@ Steps $ cd ..; cp -r forms databases; cd databases -#. We need to add some dependencies in ``databases/setup.py`` as well - as an "entry point" for the command-line script: +#. We need to add some dependencies in ``databases/setup.py`` as well as an + "entry point" for the command-line script: .. literalinclude:: databases/setup.py :linenos: .. note:: - We aren't yet doing ``$VENV/bin/pip install -e .`` as we - will change it later. + We aren't yet doing ``$VENV/bin/pip install -e .`` as we will change it + later. -#. Our configuration file at ``databases/development.ini`` wires - together some new pieces: +#. Our configuration file at ``databases/development.ini`` wires together some + new pieces: .. literalinclude:: databases/development.ini :language: ini -#. This engine configuration now needs to be read into the application - through changes in ``databases/tutorial/__init__.py``: +#. This engine configuration now needs to be read into the application through + changes in ``databases/tutorial/__init__.py``: .. literalinclude:: databases/tutorial/__init__.py :linenos: -#. Make a command-line script at ``databases/tutorial/initialize_db.py`` - to initialize the database: +#. Make a command-line script at ``databases/tutorial/initialize_db.py`` to + initialize the database: .. literalinclude:: databases/tutorial/initialize_db.py :linenos: @@ -90,51 +92,49 @@ Steps .. code-block:: bash $ $VENV/bin/initialize_tutorial_db development.ini - 2015-06-01 11:22:52,650 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1 - 2015-06-01 11:22:52,650 INFO [sqlalchemy.engine.base.Engine][MainThread] () - 2015-06-01 11:22:52,651 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1 - 2015-06-01 11:22:52,651 INFO [sqlalchemy.engine.base.Engine][MainThread] () - 2015-06-01 11:22:52,652 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") - 2015-06-01 11:22:52,652 INFO [sqlalchemy.engine.base.Engine][MainThread] () - 2015-06-01 11:22:52,653 INFO [sqlalchemy.engine.base.Engine][MainThread] + + 2016-04-16 13:01:33,055 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1 + 2016-04-16 13:01:33,055 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2016-04-16 13:01:33,056 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1 + 2016-04-16 13:01:33,056 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2016-04-16 13:01:33,057 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages") + 2016-04-16 13:01:33,057 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2016-04-16 13:01:33,058 INFO [sqlalchemy.engine.base.Engine][MainThread] CREATE TABLE wikipages ( - uid INTEGER NOT NULL, - title TEXT, - body TEXT, - PRIMARY KEY (uid), - UNIQUE (title) + uid INTEGER NOT NULL, + title TEXT, + body TEXT, + PRIMARY KEY (uid), + UNIQUE (title) ) - 2015-06-01 11:22:52,653 INFO [sqlalchemy.engine.base.Engine][MainThread] () - 2015-06-01 11:22:52,655 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT - 2015-06-01 11:22:52,658 INFO [sqlalchemy.engine.base.Engine][MainThread] BEGIN (implicit) - 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] INSERT INTO wikipages (title, body) VALUES (?, ?) - 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] ('Root', '

Root

') - 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT + 2016-04-16 13:01:33,058 INFO [sqlalchemy.engine.base.Engine][MainThread] () + 2016-04-16 13:01:33,059 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT + 2016-04-16 13:01:33,062 INFO [sqlalchemy.engine.base.Engine][MainThread] BEGIN (implicit) + 2016-04-16 13:01:33,062 INFO [sqlalchemy.engine.base.Engine][MainThread] INSERT INTO wikipages (title, body) VALUES (?, ?) + 2016-04-16 13:01:33,063 INFO [sqlalchemy.engine.base.Engine][MainThread] ('Root', '

Root

') + 2016-04-16 13:01:33,063 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT -#. With our data now driven by SQLAlchemy queries, we need to update - our ``databases/tutorial/views.py``: +#. With our data now driven by SQLAlchemy queries, we need to update our + ``databases/tutorial/views.py``: .. literalinclude:: databases/tutorial/views.py :linenos: -#. Our tests in ``databases/tutorial/tests.py`` changed to include - SQLAlchemy bootstrapping: +#. Our tests in ``databases/tutorial/tests.py`` changed to include SQLAlchemy + bootstrapping: .. literalinclude:: databases/tutorial/tests.py :linenos: -#. Run the tests in your package using ``nose``: +#. Run the tests in your package using ``py.test``: - .. code-block:: bash - - $ $VENV/bin/nosetests tutorial - .. - ----------------------------------------------------------------- - Ran 2 tests in 1.141s + .. code-block:: bash - OK + $ $VENV/bin/py.test tutorial/tests.py -q + .. + 2 passed in 1.41 seconds #. Run your Pyramid application with: @@ -144,57 +144,55 @@ Steps #. Open http://localhost:6543/ in a browser. + Analysis ======== -Let's start with the dependencies. We made the decision to use -``SQLAlchemy`` to talk to our database. We also, though, installed -``pyramid_tm`` and ``zope.sqlalchemy``. Why? +Let's start with the dependencies. We made the decision to use ``SQLAlchemy`` +to talk to our database. We also, though, installed ``pyramid_tm`` and +``zope.sqlalchemy``. Why? Pyramid has a strong orientation towards support for ``transactions``. -Specifically, you can install a transaction manager into your -application either as middleware or a Pyramid "tween". Then, -just before you return the response, all transaction-aware parts of -your application are executed. +Specifically, you can install a transaction manager into your application +either as middleware or a Pyramid "tween". Then, just before you return the +response, all transaction-aware parts of your application are executed. -This means Pyramid view code usually doesn't manage transactions. If -your view code or a template generates an error, the transaction manager -aborts the transaction. This is a very liberating way to write code. +This means Pyramid view code usually doesn't manage transactions. If your view +code or a template generates an error, the transaction manager aborts the +transaction. This is a very liberating way to write code. The ``pyramid_tm`` package provides a "tween" that is configured in the -``development.ini`` configuration file. That installs it. We then need -a package that makes SQLAlchemy, and thus the RDBMS transaction manager, -integrate with the Pyramid transaction manager. That's what -``zope.sqlalchemy`` does. +``development.ini`` configuration file. That installs it. We then need a +package that makes SQLAlchemy, and thus the RDBMS transaction manager, +integrate with the Pyramid transaction manager. That's what ``zope.sqlalchemy`` +does. Where do we point at the location on disk for the SQLite file? In the -configuration file. This lets consumers of our package change the -location in a safe (non-code) way. That is, in configuration. This -configuration-oriented approach isn't required in Pyramid; you can -still make such statements in your ``__init__.py`` or some companion -module. - -The ``initialize_tutorial_db`` is a nice example of framework support. -You point your setup at the location of some ``[console_scripts]`` and -these get generated into your virtual environment's ``bin`` directory. Our -console script follows the pattern of being fed a configuration file -with all the bootstrapping. It then opens SQLAlchemy and creates the -root of the wiki, which also makes the SQLite file. Note the -``with transaction.manager`` part that puts the work in the scope of a -transaction, as we aren't inside a web request where this is done -automatically. - -The ``models.py`` does a little bit extra work to hook up SQLAlchemy -into the Pyramid transaction manager. It then declares the model for a -``Page``. +configuration file. This lets consumers of our package change the location in a +safe (non-code) way. That is, in configuration. This configuration-oriented +approach isn't required in Pyramid; you can still make such statements in your +``__init__.py`` or some companion module. + +The ``initialize_tutorial_db`` is a nice example of framework support. You +point your setup at the location of some ``[console_scripts]``, and these get +generated into your virtual environment's ``bin`` directory. Our console script +follows the pattern of being fed a configuration file with all the +bootstrapping. It then opens SQLAlchemy and creates the root of the wiki, which +also makes the SQLite file. Note the ``with transaction.manager`` part that +puts the work in the scope of a transaction, as we aren't inside a web request +where this is done automatically. + +The ``models.py`` does a little bit of extra work to hook up SQLAlchemy into +the Pyramid transaction manager. It then declares the model for a ``Page``. Our views have changes primarily around replacing our dummy -dictionary-of-dictionaries data with proper database support: list the -rows, add a row, edit a row, and delete a row. +dictionary-of-dictionaries data with proper database support: list the rows, +add a row, edit a row, and delete a row. + -Extra Credit +Extra credit ============ -#. Why all this code? Why can't I just type 2 lines and have magic ensue? +#. Why all this code? Why can't I just type two lines and have magic ensue? #. Give a try at a button that deletes a wiki page. -- cgit v1.2.3